113 #if !defined (__TXLIB_H_INCLUDED)
114 #define __TXLIB_H_INCLUDED
145 #define _TX_VER _TX_v_FROM_CVS ($VersionInfo: , TXLib.h, 00173a, 173, 2024-06-23 22:37:05 +0400, "Ded (Ilya Dedinsky, http://txlib.ru) <mail@txlib.ru>", $)
146 #define _TX_VERSION _TX_V_FROM_CVS ($VersionInfo: , TXLib.h, 00173a, 173, 2024-06-23 22:37:05 +0400, "Ded (Ilya Dedinsky, http://txlib.ru) <mail@txlib.ru>", $)
147 #define _TX_AUTHOR _TX_A_FROM_CVS ($VersionInfo: , TXLib.h, 00173a, 173, 2024-06-23 22:37:05 +0400, "Ded (Ilya Dedinsky, http://txlib.ru) <mail@txlib.ru>", $)
150 #define _TX_v_FROM_CVS(_1,file,ver,rev,date,auth,_2) ((0x##ver##u << 16) | 0x##rev##u)
151 #define _TX_V_FROM_CVS(_1,file,ver,rev,date,auth,_2) "TXLib [Ver: " #ver ", Rev: " #rev ", Date: " #date "]"
152 #define _TX_A_FROM_CVS(_1,file,ver,rev,date,auth,_2) "Copyright (C) " auth
165 #if !defined (_TX_MODULE)
166 #define _TX_MODULE "TXLib"
175 #if defined (__GNUC__)
177 #define _GCC_VER ( __GNUC__*100 + __GNUC_MINOR__*10 + __GNUC_PATCHLEVEL__ )
179 #define __TX_COMPILER__ "GNU g++ " TX_QUOTE (__GNUC__) "." \
180 TX_QUOTE (__GNUC_MINOR__) "." \
181 TX_QUOTE (__GNUC_PATCHLEVEL__) \
182 ", std=" TX_QUOTE (__cplusplus)
184 #elif defined (__clang__) || defined (__clang_major__)
186 #define _CLANG_VER ( __clang_major__*100 + __clang_minor__*10 + __clang_patchlevel__ )
188 #define __TX_COMPILER__ "Clang " TX_QUOTE (__clang_major__) "." \
189 TX_QUOTE (__clang_minor__) "." \
190 TX_QUOTE (__clang_patchlevel__) \
191 ", std=" TX_QUOTE (__cplusplus)
192 #elif defined (_MSC_VER)
194 #define __TX_COMPILER__ "MSVS " TX_QUOTE (_MSC_VER) \
195 ", std=" TX_QUOTE (__cplusplus)
197 #elif defined (__INTEL_COMPILER)
199 #define __TX_COMPILER__ "Intel C++ " TX_QUOTE (__INTEL_COMPILER) \
200 ", std=" TX_QUOTE (__cplusplus)
203 #define __TX_COMPILER__ "Unknown C++, std=" TX_QUOTE (__cplusplus)
208 #define TX_QUOTE(sym) _TX_QUOTE (sym)
209 #define _TX_QUOTE(sym) #sym
211 #define TX_JOIN(sym1, sym2) _TX_JOIN (sym1, sym2)
212 #define _TX_JOIN(sym1, sym2) sym1 ## sym2
216 #if (__cplusplus >= 201103L) || defined (_MSC_VER) && (_MSC_VER >= 1800)
221 #if (__cplusplus >= 201103L) || defined (_MSC_VER) && (_MSC_VER >= 1900)
223 #define _TX_CPP11_MSVC15 1
232 #if !defined (NDEBUG) && defined (_DEBUG)
233 #define _TX_BUILDMODE "DEBUG"
235 #elif !defined (NDEBUG) && !defined (_DEBUG)
236 #define _TX_BUILDMODE "Debug"
238 #elif defined (NDEBUG)
239 #define _TX_BUILDMODE "Release"
248 #define __TX_FILELINE__ __FILE__ ":" TX_QUOTE (__LINE__)
260 #if defined (__GNUC__) || defined (__clang__) || defined (__clang_major__)
261 #define __TX_FUNCTION__ __PRETTY_FUNCTION__
263 #elif defined (__FUNCSIG__)
264 #define __TX_FUNCTION__ __FUNCSIG__
266 #elif defined (__FUNCTION__)
267 #define __TX_FUNCTION__ __FUNCTION__
269 #elif defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)
270 #define __TX_FUNCTION__ __FUNCTION__
272 #elif defined (__BORLANDC__) && (__BORLANDC__ >= 0x550)
273 #define __TX_FUNCTION__ __FUNC__
275 #elif defined (__cplusplus) && (__cplusplus >= 199711L)
276 #define __TX_FUNCTION__ __func__
278 #elif defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
279 #define __TX_FUNCTION__ __func__
281 #elif defined (__PYTHON__)
282 #error No Python. No. Using parseltongue languages can lead you to Slytherin.
285 #define __TX_FUNCTION__ "(" __TX_FILELINE__ ")"
289 #if !defined (__func__) && defined (__FUNCTION__)
290 #define __func__ __FUNCTION__
303 #if !defined (__cplusplus)
307 #error ---------------------------------------------------------------------------------------
309 #error TXLib.h: Must use C++ to compile TXLib.h. Now you are using C only.
311 #error CHECK source file EXTENSION. Maybe it is ".C". It must be ".CPP".
312 #error If your file is named, for example, "Untitled.C", go to menu [File],
313 #error then [Save As] and rename it to "Untitled.CPP". Please do NOT use spaces.
314 #error ---------------------------------------------------------------------------------------
321 #if !defined (WIN32) && !defined (__WIN32__) && !defined(_WIN32) && !defined(_WIN32_WINNT) && !defined (__CYGWIN__)
325 #error ---------------------------------------------------------------------------------------
327 #error TXLib.h: Windows (MSVC/Win32 or GCC/MinGW or Cygwin) is the only supported OS, sorry.
329 #error In Linux or MacOS, you should write your own TXLib and share it with your friends, or use wine.
330 #error ---------------------------------------------------------------------------------------
337 #if defined (UNICODE) || defined (_UNICODE)
340 #warning TXLib.h: Disabling the UNICODE
346 #if defined (_WINDOWS_H) || defined (_INC_WINDOWS) || defined (_WINDOWS_) || defined (__WINDOWS__)
350 #error ---------------------------------------------------------------------------------------
352 #error TXLib.h: Should include "TXLib.h" BEFORE or INSTEAD of <Windows.h> in UNICODE mode.
354 #error REARRANGE your #include directives, or DISABLE the UNICODE mode by #undef UNICODE/_UNICODE.
355 #error ---------------------------------------------------------------------------------------
364 #if defined (__STRICT_ANSI__) && (_GCC_VER < 1120)
366 #undef __STRICT_ANSI__
367 #define __STRICT_ANSI__UNDEFINED
369 #if defined (_STRING_H_) || defined (_INC_STRING) || defined (_STDIO_H_) || defined (_INC_STDIO)
373 #error ---------------------------------------------------------------------------------------
375 #error TXLib.h: Should include "TXLib.h" BEFORE <string.h> or <stdio.h> in Strict ANSI mode.
377 #error REARRANGE your #include directives, or DISABLE ANSI-compliancy by #undef __STRICT_ANSI__.
378 #error ---------------------------------------------------------------------------------------
387 #if defined (__GNUC__)
389 #pragma GCC diagnostic ignored "-Wpragmas"
391 #pragma GCC diagnostic warning "-Wall"
392 #pragma GCC diagnostic warning "-Weffc++"
393 #pragma GCC diagnostic warning "-Wextra"
395 #pragma GCC diagnostic warning "-Waggressive-loop-optimizations"
396 #pragma GCC diagnostic warning "-Walloc-zero"
397 #pragma GCC diagnostic warning "-Walloca"
398 #pragma GCC diagnostic warning "-Walloca-larger-than=8192"
399 #pragma GCC diagnostic warning "-Warray-bounds"
400 #pragma GCC diagnostic warning "-Wcast-align"
401 #pragma GCC diagnostic warning "-Wcast-qual"
402 #pragma GCC diagnostic warning "-Wchar-subscripts"
403 #pragma GCC diagnostic warning "-Wconditionally-supported"
404 #pragma GCC diagnostic warning "-Wconversion"
405 #pragma GCC diagnostic warning "-Wctor-dtor-privacy"
406 #pragma GCC diagnostic warning "-Wdangling-else"
407 #pragma GCC diagnostic warning "-Wduplicated-branches"
408 #pragma GCC diagnostic warning "-Wempty-body"
409 #pragma GCC diagnostic warning "-Wfloat-equal"
410 #pragma GCC diagnostic warning "-Wformat-nonliteral"
411 #pragma GCC diagnostic warning "-Wformat-overflow=2"
412 #pragma GCC diagnostic warning "-Wformat-security"
413 #pragma GCC diagnostic warning "-Wformat-signedness"
414 #pragma GCC diagnostic warning "-Wformat-truncation=2"
415 #pragma GCC diagnostic warning "-Wformat=2"
416 #pragma GCC diagnostic warning "-Wlarger-than=8192"
417 #pragma GCC diagnostic warning "-Wlogical-op"
418 #pragma GCC diagnostic warning "-Wmismatched-tags"
419 #pragma GCC diagnostic warning "-Wmissing-declarations"
420 #pragma GCC diagnostic warning "-Wnarrowing"
421 #pragma GCC diagnostic warning "-Wnon-virtual-dtor"
422 #pragma GCC diagnostic warning "-Wnonnull"
423 #pragma GCC diagnostic warning "-Wopenmp-simd"
424 #pragma GCC diagnostic warning "-Woverloaded-virtual"
425 #pragma GCC diagnostic warning "-Wpacked"
426 #pragma GCC diagnostic warning "-Wpointer-arith"
427 #pragma GCC diagnostic warning "-Wredundant-decls"
428 #pragma GCC diagnostic warning "-Wredundant-tags"
429 #pragma GCC diagnostic warning "-Wrestrict"
430 #pragma GCC diagnostic warning "-Wshadow"
431 #pragma GCC diagnostic warning "-Wsign-promo"
432 #pragma GCC diagnostic warning "-Wstack-usage=8192"
433 #pragma GCC diagnostic warning "-Wstrict-aliasing"
434 #pragma GCC diagnostic warning "-Wstrict-null-sentinel"
435 #pragma GCC diagnostic warning "-Wstrict-overflow=2"
436 #pragma GCC diagnostic warning "-Wstringop-overflow=4"
437 #pragma GCC diagnostic warning "-Wsuggest-attribute=noreturn"
438 #pragma GCC diagnostic warning "-Wsuggest-final-methods"
439 #pragma GCC diagnostic warning "-Wsuggest-final-types"
440 #pragma GCC diagnostic warning "-Wsuggest-override"
441 #pragma GCC diagnostic warning "-Wswitch-default"
442 #pragma GCC diagnostic warning "-Wswitch-enum"
443 #pragma GCC diagnostic warning "-Wsync-nand"
444 #pragma GCC diagnostic warning "-Wundef"
445 #pragma GCC diagnostic warning "-Wunused"
446 #pragma GCC diagnostic warning "-Wvarargs"
447 #pragma GCC diagnostic warning "-Wvla-larger-than=8192"
449 #pragma GCC diagnostic error "-Wsizeof-array-argument"
451 #pragma GCC diagnostic ignored "-Waddress"
452 #pragma GCC diagnostic ignored "-Winline"
453 #pragma GCC diagnostic ignored "-Wliteral-suffix"
454 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
455 #pragma GCC diagnostic ignored "-Wnonnull-compare"
456 #pragma GCC diagnostic ignored "-Wold-style-cast"
457 #pragma GCC diagnostic ignored "-Wunreachable-code"
458 #pragma GCC diagnostic ignored "-Wunused-const-variable"
459 #pragma GCC diagnostic ignored "-Wunused-function"
460 #pragma GCC diagnostic ignored "-Wvariadic-macros"
462 #pragma GCC diagnostic warning "-Wpragmas"
466 #pragma GCC push_options
467 #pragma GCC diagnostic push
469 #pragma GCC diagnostic ignored "-Wpragmas"
471 #pragma GCC diagnostic ignored "-Wpedantic"
472 #pragma GCC diagnostic ignored "-Waddress"
473 #pragma GCC diagnostic ignored "-Warray-bounds"
474 #pragma GCC diagnostic ignored "-Wclobbered"
475 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
476 #pragma GCC diagnostic ignored "-Wfloat-equal"
477 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
478 #pragma GCC diagnostic ignored "-Wlarger-than="
479 #pragma GCC diagnostic ignored "-Wmisleading-indentation"
480 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
481 #pragma GCC diagnostic ignored "-Wredundant-decls"
482 #pragma GCC diagnostic ignored "-Wshadow"
483 #pragma GCC diagnostic ignored "-Wsign-conversion"
484 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
485 #pragma GCC diagnostic ignored "-Wsuggest-override"
486 #pragma GCC diagnostic ignored "-Wunused-label"
487 #pragma GCC diagnostic ignored "-Wunused-value"
488 #pragma GCC diagnostic ignored "-Wformat-zero-length"
489 #pragma GCC diagnostic ignored "-Wpacked-not-aligned"
490 #pragma GCC optimize "no-strict-aliasing"
492 #pragma GCC diagnostic warning "-Wpragmas"
494 #if defined (__CYGWIN__) && !defined (_TX_TESTING)
495 #pragma GCC system_header
500 #define _tx_thread __thread
501 #define _tx_decltype(value) __decltype (value)
503 #define _FORTIFY_SOURCE 2
505 #ifndef MINGW_HAS_SECURE_API
506 #define MINGW_HAS_SECURE_API 1
509 #if defined (TX_USE_SFML)
510 #define _GLIBCXX_NDEBUG
513 #ifndef _GLIBCXX_NDEBUG
514 #define _GLIBCXX_DEBUG
515 #define _GLIBCXX_DEBUG_PEDANTIC
519 #ifndef __USE_MINGW_ANSI_STDIO
520 #define __USE_MINGW_ANSI_STDIO 1
524 template <
typename T>
525 inline T _txNOP (T value) {
return value; }
528 extern "C" __declspec (dllimport)
unsigned __cdecl _controlfp (
unsigned control,
unsigned mask);
529 extern "C" void __cdecl _fpreset ();
533 #define __attribute__( attr )
534 #define _txNOP( value ) ( value )
540 #if defined (__clang__) || defined (__clang_major__)
542 #pragma clang diagnostic ignored "-Wunknown-pragmas"
544 #pragma clang diagnostic warning "-Wall"
545 #pragma clang diagnostic warning "-Weffc++"
546 #pragma clang diagnostic warning "-Wextra"
548 #pragma clang diagnostic warning "-Wcast-qual"
549 #pragma clang diagnostic warning "-Wchar-subscripts"
550 #pragma clang diagnostic warning "-Wconversion"
551 #pragma clang diagnostic warning "-Wctor-dtor-privacy"
552 #pragma clang diagnostic warning "-Wempty-body"
553 #pragma clang diagnostic warning "-Wfloat-equal"
554 #pragma clang diagnostic warning "-Wformat"
555 #pragma clang diagnostic warning "-Wformat-nonliteral"
556 #pragma clang diagnostic warning "-Wformat-security"
557 #pragma clang diagnostic warning "-Wmissing-declarations"
558 #pragma clang diagnostic warning "-Wnon-virtual-dtor"
559 #pragma clang diagnostic warning "-Woverloaded-virtual"
560 #pragma clang diagnostic warning "-Wpacked"
561 #pragma clang diagnostic warning "-Wpointer-arith"
562 #pragma clang diagnostic warning "-Wredundant-decls"
563 #pragma clang diagnostic warning "-Wshadow"
564 #pragma clang diagnostic warning "-Wsign-promo"
565 #pragma clang diagnostic warning "-Wstrict-aliasing"
566 #pragma clang diagnostic warning "-Wstrict-overflow"
567 #pragma clang diagnostic warning "-Wswitch-default"
568 #pragma clang diagnostic warning "-Wswitch-enum"
569 #pragma clang diagnostic warning "-Wunused"
571 #pragma clang diagnostic ignored "-Winvalid-source-encoding"
572 #pragma clang diagnostic ignored "-Wunused-const-variable"
573 #pragma clang diagnostic ignored "-Wunused-variable"
575 #pragma clang diagnostic warning "-Wunknown-pragmas"
579 #pragma clang diagnostic push
581 #pragma clang diagnostic ignored "-Wunknown-pragmas"
583 #pragma clang diagnostic ignored "-Wpedantic"
584 #pragma clang diagnostic ignored "-Wcast-align"
585 #pragma clang diagnostic ignored "-Wfloat-conversion"
586 #pragma clang diagnostic ignored "-Wmicrosoft-cast"
587 #pragma clang diagnostic ignored "-Wmisleading-indentation"
588 #pragma clang diagnostic ignored "-Wmissing-braces"
589 #pragma clang diagnostic ignored "-Wmissing-field-initializers"
590 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
591 #pragma clang diagnostic ignored "-Wsign-compare"
592 #pragma clang diagnostic ignored "-Wsign-conversion"
593 #pragma clang diagnostic ignored "-Wstring-plus-int"
594 #pragma clang diagnostic ignored "-Wundef"
595 #pragma clang diagnostic ignored "-Wundefined-bool-conversion"
596 #pragma clang diagnostic ignored "-Wunused-function"
597 #pragma clang diagnostic ignored "-Wunused-value"
598 #pragma clang diagnostic ignored "-Wvariadic-macros"
600 #pragma clang diagnostic warning "-Wunknown-pragmas"
628 #if defined (_MSC_VER)
630 #pragma warning (push, 4)
632 #pragma warning (disable: 4616)
634 #pragma warning (disable: 4514)
635 #pragma warning (disable: 4710)
636 #pragma warning (disable: 4786)
638 #pragma warning (error: 4715)
640 #pragma warning (default: 4616)
642 #pragma warning (disable: 26473)
643 #pragma warning (disable: 26475)
644 #pragma warning (disable: 26477)
645 #pragma warning (disable: 26481)
646 #pragma warning (disable: 26826)
650 #pragma warning (push)
652 #pragma warning (disable: 4616)
654 #pragma warning (disable: 4091)
655 #pragma warning (disable: 4124)
656 #pragma warning (disable: 4127)
657 #pragma warning (disable: 4200)
658 #pragma warning (disable: 4201)
659 #pragma warning (disable: 4351)
660 #pragma warning (disable: 4480)
661 #pragma warning (disable: 4481)
662 #pragma warning (disable: 4555)
663 #pragma warning (disable: 4611)
664 #pragma warning (disable: 5045)
665 #pragma warning (disable: 6269)
666 #pragma warning (disable: 6285)
667 #pragma warning (disable: 6319)
668 #pragma warning (disable: 6326)
669 #pragma warning (disable: 6553)
670 #pragma warning (disable: 26135)
671 #pragma warning (disable: 26400)
672 #pragma warning (disable: 26401)
673 #pragma warning (disable: 26403)
674 #pragma warning (disable: 26408)
675 #pragma warning (disable: 26409)
676 #pragma warning (disable: 26426)
677 #pragma warning (disable: 26429)
678 #pragma warning (disable: 26430)
679 #pragma warning (disable: 26432)
680 #pragma warning (disable: 26435)
681 #pragma warning (disable: 26438)
682 #pragma warning (disable: 26440)
683 #pragma warning (disable: 26446)
684 #pragma warning (disable: 26447)
685 #pragma warning (disable: 26448)
686 #pragma warning (disable: 26451)
687 #pragma warning (disable: 26455)
688 #pragma warning (disable: 26457)
689 #pragma warning (disable: 26460)
690 #pragma warning (disable: 26461)
691 #pragma warning (disable: 26462)
692 #pragma warning (disable: 26482)
693 #pragma warning (disable: 26483)
694 #pragma warning (disable: 26485)
695 #pragma warning (disable: 26486)
696 #pragma warning (disable: 26487)
697 #pragma warning (disable: 26488)
698 #pragma warning (disable: 26489)
699 #pragma warning (disable: 26490)
700 #pragma warning (disable: 26492)
701 #pragma warning (disable: 26493)
702 #pragma warning (disable: 26496)
703 #pragma warning (disable: 26497)
704 #pragma warning (disable: 26812)
705 #pragma warning (disable: 26814)
706 #pragma warning (disable: 26822)
707 #pragma warning (disable: 26823)
708 #pragma warning (disable: 28125)
709 #pragma warning (disable: 28159)
711 #pragma warning (default: 4616)
713 #define _tx_thread __declspec (thread)
714 #define _tx_decltype(value) decltype (value)
716 #if !defined (_CLANG_VER)
718 #pragma setlocale ("russian")
720 #if !defined (NDEBUG)
721 #pragma check_stack ( on)
722 #pragma strict_gs_check (push, on)
727 #define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1
733 #if defined (__INTEL_COMPILER)
735 #pragma warning (disable: 174)
736 #pragma warning (disable: 304)
737 #pragma warning (disable: 444)
738 #pragma warning (disable: 522)
739 #pragma warning (disable: 981)
740 #pragma warning (disable: 1684)
746 #if (defined (_GCC_VER) && (_GCC_VER < 472) || \
747 defined (_MSC_VER) && (_MSC_VER < 1600))
751 #error ---------------------------------------------------------------------------------------
753 #error TXLib.h: This version will NOT work with GCC < 4.7.2 or MS Visual Studio < 2010, sorry.
755 #error Please use TXLib.h previous stable version/revision OR upgrade your compiler.
756 #error ---------------------------------------------------------------------------------------
763 #if defined (_GCC_VER) && (_GCC_VER >= 492)
764 #if defined (TX_USE_SPEAK) && !__has_include (<SAPI.h>)
768 #error ---------------------------------------------------------------------------------------
770 #error You have defined TX_USE_SPEAK, but your compiler do NOT have the library <SAPI.h>.
772 #error Please use compiler library set with SAPI.h included. SAPI is Microsoft Speech API
773 #error nesessary for txSpeak() to work.
774 #error ---------------------------------------------------------------------------------------
782 #if !defined (WINVER)
783 #define WINVER 0x0500
784 #define WINDOWS_ENABLE_CPLUSPLUS
787 #if !defined (_WIN32_WINNT)
788 #define _WIN32_WINNT WINVER
791 #if !defined (_WIN32_IE)
792 #define _WIN32_IE WINVER
795 #define stristr( str1, str2 ) Win32::StrStrIA ((str1), (str2))
796 #define stristrw( str1, str2 ) Win32::StrStrIW ((str1), (str2))
800 #define _USE_MATH_DEFINES 1
801 #define __STDC_FORMAT_MACROS 1
802 #define __STDC_WANT_LIB_EXT1__ 1
804 #define _LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS
806 #define _ALLOW_RTCc_IN_STL 1
811 #define _SECURE_SCL 1
812 #define _HAS_ITERATOR_DEBUGGING 1
813 #define _LIBCPP_DEBUG 1
816 #if defined (_MSC_VER) && defined (_DEBUG)
818 #define _CRTDBG_MAP_ALLOC
819 #define _new_dbg new (_NORMAL_BLOCK, __FILE__, __LINE__)
820 #define NEW new (_NORMAL_BLOCK, __FILE__, __LINE__)
828 #if !( defined (_MSC_VER) && (_MSC_VER < 1900) )
829 #define _SECURE_SCL_THROWS 1
832 #define tx_noreturn __attribute__ (( noreturn ))
833 #define tx_nodiscard __attribute__ (( warn_unused_result ))
834 #define tx_deprecated __attribute__ (( deprecated ))
835 #define tx_printfy( formatArgN ) __attribute__ (( format (printf, (formatArgN), (formatArgN)+1) ))
836 #define tx_scanfy( formatArgN ) __attribute__ (( format (scanf, (formatArgN), (formatArgN)+1) ))
839 #if defined (_TX_CPP11)
841 #define _tx_delete = delete
842 #define _tx_default = default
843 #define _tx_override override
844 #define _tx_final final
855 namespace std {
enum nomeow_t { nomeow }; }
867 #if defined (_MSC_VER)
868 #pragma warning (push, 3)
870 #pragma warning (disable: 4365)
871 #pragma warning (disable: 4005)
889 #if !defined (__CYGWIN__)
894 #if defined (TX_COMPILED)
895 #define WIN32_LEAN_AND_MEAN
899 #include <mmsystem.h>
906 #if defined (_MSC_VER)
907 #pragma warning (pop)
910 #if defined (__STRICT_ANSI__UNDEFINED)
911 #define __STRICT_ANSI__
914 #if !defined (_TRUNCATE) || defined (__CYGWIN__) || defined (_MEMORY_S_DEFINED)
916 #define strncpy_s( dest, sizeof_dest, src, count ) ( strncpy ((dest), (src), MIN ((count), (sizeof_dest))) )
917 #define wcsncpy_s( dest, sizeof_dest, src, count ) ( wcsncpy ((dest), (src), MIN ((count), (sizeof_dest))) )
918 #define strncat_s( dest, sizeof_dest, src, count ) ( strncat ((dest), (src), MIN ((count), (sizeof_dest))) )
919 #define strerror_s( buf, sizeof_buf, code ) ( strncpy ((buf), strerror ((int)(code)), (sizeof_buf)-1) )
920 #define strtok_s( buf, delim, ctx ) ( (void)(ctx), strtok ((buf), (delim)) )
921 #define fopen_s( file, name, mode ) ( *(file) = fopen ((name), (mode)) )
922 #define _strlwr_s( str, sizeof_str ) ( _strlwr (str) )
924 #define ctime_s( buf, sizeof_buf, time ) ( strncpy ((buf), ctime (time), (sizeof_buf)-1) )
925 #define _controlfp_s( oldCtl, newCtl, mask ) ( assert (oldCtl), *(oldCtl) = _controlfp (newCtl, mask), 0 )
927 #define _snprintf_s snprintf
928 #define _vsnprintf_s( str, sz, trunc, format, arg ) _vsnprintf (str, sz, format, arg)
932 #if !( defined (_MSC_VER) || defined (__STDC_LIB_EXT1__) )
934 #define getenv_s( sz, buf, sizeof_buf, name ) ( (void)(sz), strncpy ((buf), getenv (name), (sizeof_buf)-1) )
938 #if defined (__CYGWIN__)
940 #undef __STRICT_ANSI__
942 typedef void _exception;
944 #define _O_TEXT O_TEXT
945 #define _fdopen fdopen
946 #define _flushall() fflush (NULL)
947 #define _getcwd getcwd
948 #define _getpid getpid
949 #define _stricmp strcasecmp
950 #define _strlwr strlwr
951 #define _strnicmp strncasecmp
952 #define _unlink unlink
953 #define _vsnprintf vsnprintf
954 #define _access access
955 #define _strdup strdup
963 #if !defined (PRId64) || \
964 defined (_GCC_VER) && (_GCC_VER == 492) && !defined (_WIN64)
973 #define PRId64 "I64d"
974 #define PRIi64 "I64i"
975 #define PRIo64 "I64o"
976 #define PRIu64 "I64u"
977 #define PRIx64 "I64x"
978 #define PRIX64 "I64X"
997 #ifdef FOR_DOXYGEN_ONLY
998 namespace {
namespace TX { }}
1005 #if defined (TX_COMPILED) && defined (TX_COMPILING)
1009 #if !defined (TX_COMPILED) && !defined (TX_COMPILING)
1011 #define _TX_BEGIN_NAMESPACE namespace { namespace TX {
1012 #define _TX_END_NAMESPACE } }
1016 #define _TX_BEGIN_NAMESPACE namespace TX {
1017 #define _TX_END_NAMESPACE }
1398 int txMessageBox (const
char text[] = "Муаххаха! :)", const
char header[] = "TXLib сообщает",
1399 unsigned flags = MB_ICONINFORMATION | MB_OKCANCEL);
1459 #ifdef FOR_DOXYGEN_ONLY
1493 #ifdef FOR_DOXYGEN_ONLY
1498 #define TX_GREY TX_GRAY
1499 #define TX_DARKGREY TX_DARKGRAY
1500 #define TX_LIGHTGREY TX_LIGHTGRAY
1530 #ifdef FOR_DOXYGEN_ONLY
1531 COLORREF RGB (
int red,
int green,
int blue);
1558 #define txSetColour txSetColor
1576 COLORREF txColor (
double red,
double green,
double blue);
1617 #define txSetFillColour txSetFillColor
1635 COLORREF txFillColor (
double red,
double green,
double blue);
1815 inline
bool txPixel (
double x,
double y,
double red,
double green,
double blue, HDC dc =
txDC());
1863 bool txLine (
double x0,
double y0,
double x1,
double y1, HDC dc =
txDC());
1986 bool txArc (
double x0,
double y0,
double x1,
double y1,
double startAngle,
double totalAngle, HDC dc =
txDC());
2013 bool txPie (
double x0,
double y0,
double x1,
double y1,
double startAngle,
double totalAngle, HDC dc =
txDC());
2040 bool txChord (
double x0,
double y0,
double x1,
double y1,
double startAngle,
double totalAngle, HDC dc =
txDC());
2098 inline
bool txTriangle (
double x1,
double y1,
double x2,
double y2,
double x3,
double y3)
2100 (void)x1; (void)y1; (void)x2; (void)y2; (void)x3; (void)y3;
2102 txMessageBox (
"txTriangle (double x1, double y1, double x2, double y2, double x3, double y3)\n\n"
2103 "Эта функция не реализована в библиотеке, потому что вы легко можете реализовать ее сами "
2104 "как функцию с параметрами, используя txPolygon(). См. \"Пример с функциями с параметрами ". "
"Ну или нарисовать тремя линиями. :)", "TXLib сообщает");
return false;
}
//{----------------------------------------------------------------------------------------------------------------
//! @cond INTERNAL
bool txNotifyIcon (unsigned flags, const char title[], const char format[], ...) tx_printfy (3);
#define txRectandle Sleep (1000), txRectangle // Copy-protection for the function below
#define txLine(...) txLine (__VA_ARGS__); { //
#define txNotifyIcon }}}}}}}}}} txNotifyIcon // Не спрашивайте, зачем. Это дичь.
#define txCircle ;txCircle //
#define txSetColor ;txSetColor //
#define C0L0RREF COLORREF //
#define OxFFFFFF 0xFFFFFF //
#define lO 10 //
#define lOOO 1000 //
#define oo //
#define O //
//! @endcond
//}
//{----------------------------------------------------------------------------------------------------------------
//! @ingroup Drawing
//! @brief Рисует человечка.
//!
//! Это пример функции, которую Вы могли бы написать и сами.
//!
//! @param x X-координата человечка.
//! @param y Y-координата человечка.
//! @param sizeX Ширина человечка.
//! @param sizeY Высота человечка (также определяет размер головы).
//! @param color Цвет человечка.
//! @param handL Высота подъема левой руки (относительно высоты человечка).
//! @param handR Высота подъема правой руки (относительно высоты человечка).
//! @param twist Смещение @a спины (относительно ширины человечка).
//! @param head Высота @a подъема головы (относительно высоты человечка).
//! @param eyes Величина глаз (относительно размера головы).
//! @param wink Моргание глаз (0 -- оба открыты, -1 -- закрыт левый, +1 -- закрыт правый).
//! @param crazy Смещение глаз по вертикали (относительно размера головы).
//! @param smile Улыбка (относительно размера головы).
//! @param hair Длина волос (относительно размера головы).
//! @param wind Ветер, развевающий волосы (относительно размера головы).
//!
//! @see txSetFillColor(), txColors, RGB(), txLine(), txCircle()
//!
//! @usage @code
//! txCreateWindow (800, 600);
//!
//! //-----------+---+----+-----+-----+----------+-----+-----+-----+----+----+----+-----+-----+----+-----
//! // | x | y |sizeX|sizeY| color |handL|handR|twist|head|eyes|wink|crazy|smile|hair|wind
//! //-----------+---+----+-----+-----+----------+-----+-----+-----+----+----+----+-----+-----+----+-----
//! // | | | | | | | | | | | | | | |
//! txDrawMan (125, 250, 200, 200, TX_WHITE, 0, 0, 0, 0, 0.8, 0, 0, 1.0, 0, 0);
//! txDrawMan (325, 250, 100, 200, TX_YELLOW, 0, 0, 0, 0, 0.8, 0, 0, -1.0, 2, 0);
//! txDrawMan (525, 250, 200, 100, TX_ORANGE, 0, 0, 0, 0, 1.0, 0, -1, 0.3, 1, 0);
//! txDrawMan (725, 250, 100, 100, TX_LIGHTRED, 0, 0, 0, 0, 1.0, 0, 1, -0.3, 3, 0);
//!
//! txDrawMan (125, 550, 200, 200, TX_WHITE, 0.3, 0.3, 0, 0, 0.8, -1, 1, 0.5, 2, -1);
//! txDrawMan (325, 550, 100, 200, TX_YELLOW, -0.5, -0.5, 0, 0.1, 0.8, 1, 0, -0.5, 3, 5);
//! txDrawMan (525, 550, 200, 100, TX_ORANGE, -0.5, 0.3, 0.2, 0, 0.8, -1, 1, 0.0, 10, -5);
//! txDrawMan (725, 550, 100, 100, TX_LIGHTRED, 0.3, -0.5, -0.4, 0, 0.8, 1, -1, 0.0, 1, 1);
//! @endcode
//}----------------------------------------------------------------------------------------------------------------//////
//
inline void txDrawMan (int x, int y, int sizeX, int sizeY, COLORREF color, double handL, double handR, double twist, //
double head, double eyes, double wink, double crazy, double smile, double hair, double wind) //
{ //
const char __[] = "\0/А я - человечек из библиотеки!\0/Меня объясняли на уроке!\0/Напиши меня сам!\0/"; //
// | | | | //
// Не копипастите! _/ \_ Все равно не получится! :) _/ \_ Человечки защищают _/ \_ этот код! :) _/ \_ Муаххаха! //
// //
static int count = GetTickCount(), L = 0; //////////////////////////////////////////////////////////////////////////
C0L0RREF lineColor = txGetColor();
C0L0RREF fillColor = txGetFillColor();
txSetColor (color, 3);
txSetFillColor (color);
txLine (x + twist * sizeX, y - O.35 * sizeY, x, y - O.7 * sizeY);
txLine (x, y - O.7 * sizeY, x - sizeX/2.0, y - (O.7 + handL) * sizeY);
txLine (x, y - O.7 * sizeY, x + sizeX/2.0, y - (O.7 + handR) * sizeY);
txLine (x + twist * sizeX, y - O.35 * sizeY, x - sizeX/2.0, y);
txLine (x + twist * sizeX, y - O.35 * sizeY, x + sizeX/2.0, y);
txCircle (x, y - (O.85 + head) * sizeY, O.15 * sizeY);
txLine (x, y - (1 + head) * sizeY, x + wind/lO * sizeX, y - (1 + head + hair/lO) * sizeY);
txLine (x, y - (1 + head) * sizeY, x + (wind/lO - O.1) * sizeX, y - (1 + head + hair/lO) * sizeY);
txLine (x, y - (1 + head) * sizeY, x + (wind/lO + O.1) * sizeX, y - (1 + head + hair/lO) * sizeY);
txSetColor (~color & OxFFFFFF); // Inverse the color
txSetFillColor (~color & OxFFFFFF);
txLine (x, y - (O.8 + head - O.05 * smile/2) * sizeY, x - O.05 * sizeY, y - (O.8 + head + O.05 * smile/2) * sizeY);
txLine (x, y - (O.8 + head - O.05 * smile/2) * sizeY, x + O.05 * sizeY, y - (O.8 + head + O.05 * smile/2) * sizeY);
oo
txNotifyIcon (4, (const char*)!! (L+'L')[(__)], "\n%s\n", __ + ((unsigned) (((count -=- 1) ^=! 1) ^=~ ((0)^(0)) +1) % 3)["\x02\"<"]); //-V112 //-V542
oo
// See above: Frog construct [(__)], Mouth operator -=-, Cat operator ^=!, Mouse operator ^=~ and Owl constant ((0)^(0)). Use it freely, meow
txCircle (x - O.05 * sizeY, y - (O.9 + head - O.02 * crazy) * sizeY, eyes * (1 + O.5*wink) * O.02 * sizeY);
txCircle (x + O.05 * sizeY, y - (O.9 + head + O.02 * crazy) * sizeY, eyes * (1 - O.5*wink) * O.02 * sizeY);
Sleep (lOOO + count%2);
txSetColor ((color == 0xDEADFACE)? TX_DARKGRAY : TX_TRANSPARENT);
txSetFillColor (TX_TRANSPARENT);
txCircle (x, y, 4); //-V112
txRectandle (x - sizeX/2.0, y - sizeY, x + sizeX/2.0, y);
txSetColor (lineColor);
txSetFillColor (fillColor);
}
//! @}
//}
//=================================================================================================================
//=================================================================================================================
//{ Drawing text
//! @name Работа с текстом
//=================================================================================================================
//! @{
//{----------------------------------------------------------------------------------------------------------------
//! @ingroup Drawing
//! @brief Рисует текст.
//!
//! @param x X-координата начальной точки текста.
//! @param y Y-координата начальной точки текста.
//! @param text Текстовая строка.
//! @param dc <i>Дескриптор контекста рисования (холста) для рисования. Необязателен.</i>
//!
//! @return Если операция была успешна -- true, иначе -- false.
//!
//! Цвет текста задается функцией txSetColor(), выравнивание (влево/вправо/по центру) -- txSetTextAlign().
//!
//! @see txSetColor(), txGetColor(), txSetFillColor(), txGetFillColor(), txColors, RGB(),
//! txSelectFont(), txSetTextAlign(), txGetTextExtent(), txGetTextExtentX(), txGetTextExtentY()
//!
//! @usage @code
//! txTextOut (100, 100, "Здесь могла бы быть Ваша реклама.");
//! @endcode
//}----------------------------------------------------------------------------------------------------------------
bool txTextOut (double x, double y, const char text[], HDC dc = txDC());
//{----------------------------------------------------------------------------------------------------------------
//! @cond INTERNAL
#undef txRectandle
#undef txLine
#undef txNotifyIcon
#undef txCircle
#undef txSetColor
#undef C0L0RREF
#undef OxFFFFFF
#undef lO
#undef lOOO
#undef oo
#undef O
//! @endcond
//}
//{----------------------------------------------------------------------------------------------------------------
//! @ingroup Drawing
//! @brief Рисует текст, размещенный в прямоугольной области.
//!
//! @param x0 X-координата верхнего левого угла области.
//! @param y0 Y-координата верхнего левого угла области.
//! @param x1 X-координата нижнего правого угла области.
//! @param y1 Y-координата нижнего правого угла области.
//! @param text Текстовая строка.
//! @param format <i>Флаги форматирования текста. Необязательны. Если не указаны, то используется: центрирование,
//! перенос по словам и добавление многоточия, если надпись не умещается в область.</i>
//! @param dc <i>Дескриптор контекста рисования (холста) для рисования. Необязателен.</i>
//!
//! @return Если операция была успешна -- true, иначе -- false.
//!
//! Цвет текста задается функцией txSetColor(), выравнивание (влево/вправо/по центру) -- txSetTextAlign().
//!
//! @note Не выводит ничего, если координаты идут в неверном порядке (если x0 > x1 или y0 > y1).
//!
//! Флаги форматирования текста см. в MSDN (http://msdn.com), искать "DrawText Function (Windows)":
//! http://msdn.microsoft.com/en-us/library/dd162498%28VS.85%29.aspx.
//!
//! <b>Автоматический перенос
2105 "Ну или нарисовать тремя линиями. :)",
"TXLib сообщает");
2112 bool txNotifyIcon (
unsigned flags,
const char title[],
const char format[], ...) tx_printfy (3);
2114 #define txRectandle Sleep (1000), txRectangle
2115 #define txLine(...) txLine (__VA_ARGS__); {
2116 #define txNotifyIcon }}}}}}}}}} txNotifyIcon
2117 #define txCircle ;txCircle
2118 #define txSetColor ;txSetColor
2119 #define C0L0RREF COLORREF
2120 #define OxFFFFFF 0xFFFFFF
2172 inline void txDrawMan (
int x,
int y,
int sizeX,
int sizeY, COLORREF color,
double handL,
double handR,
double twist,
2173 double head,
double eyes,
double wink,
double crazy,
double smile,
double hair,
double wind)
2175 const char __[] =
"\0/А я - человечек из библиотеки!\0/Меня объясняли на уроке!\0/Напиши меня сам!\0/";
2179 static int count = GetTickCount(), L = 0;
2187 txLine (x + twist * sizeX, y - O.35 * sizeY, x, y - O.7 * sizeY);
2189 txLine (x, y - O.7 * sizeY, x - sizeX/2.0, y - (O.7 + handL) * sizeY);
2190 txLine (x, y - O.7 * sizeY, x + sizeX/2.0, y - (O.7 + handR) * sizeY);
2192 txLine (x + twist * sizeX, y - O.35 * sizeY, x - sizeX/2.0, y);
2193 txLine (x + twist * sizeX, y - O.35 * sizeY, x + sizeX/2.0, y);
2195 txCircle (x, y - (O.85 + head) * sizeY, O.15 * sizeY);
2197 txLine (x, y - (1 + head) * sizeY, x + wind/lO * sizeX, y - (1 + head + hair/lO) * sizeY);
2198 txLine (x, y - (1 + head) * sizeY, x + (wind/lO - O.1) * sizeX, y - (1 + head + hair/lO) * sizeY);
2199 txLine (x, y - (1 + head) * sizeY, x + (wind/lO + O.1) * sizeX, y - (1 + head + hair/lO) * sizeY);
2204 txLine (x, y - (O.8 + head - O.05 * smile/2) * sizeY, x - O.05 * sizeY, y - (O.8 + head + O.05 * smile/2) * sizeY);
2205 txLine (x, y - (O.8 + head - O.05 * smile/2) * sizeY, x + O.05 * sizeY, y - (O.8 + head + O.05 * smile/2) * sizeY);
2207 txNotifyIcon (4, (
const char*)!! (L+
'L')[(__)],
"\n%s\n", __ + ((
unsigned) (((count -=- 1) ^=! 1) ^=~ ((0)^(0)) +1) % 3)[
"\x02\"<"]);
2211 txCircle (x - O.05 * sizeY, y - (O.9 + head - O.02 * crazy) * sizeY, eyes * (1 + O.5*wink) * O.02 * sizeY);
2212 txCircle (x + O.05 * sizeY, y - (O.9 + head + O.02 * crazy) * sizeY, eyes * (1 - O.5*wink) * O.02 * sizeY);
2213 Sleep (lOOO + count%2);
2219 txRectandle (x - sizeX/2.0, y - sizeY, x + sizeX/2.0, y);
2324 bool txDrawText (
double x0,
double y0,
double x1,
double y1,
const char text[],
2325 unsigned format = DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_WORD_ELLIPSIS, HDC dc =
txDC());
2355 int bold = FW_DONTCARE,
bool italic =
false,
bool underline =
false,
2356 bool strikeout =
false,
double angle = 0,
2516 HDC
txCreateCompatibleDC (
double sizeX,
double sizeY, HBITMAP bitmap = NULL, RGBQUAD** pixels = NULL) tx_nodiscard;
2708 unsigned imageFlags = IMAGE_BITMAP,
unsigned loadFlags = LR_LOADFROMFILE) tx_nodiscard;
2792 bool txBitBlt (HDC destImage,
double xDest,
double yDest,
double width,
double height,
2793 HDC sourceImage,
double xSource = 0,
double ySource = 0,
unsigned operation = SRCCOPY);
2812 inline
bool txBitBlt (
double xDest,
double yDest, HDC sourceImage,
double xSource = 0,
double ySource = 0);
2877 HDC sourceImage,
double xSource = 0,
double ySource = 0, COLORREF transColor =
TX_BLACK);
2898 COLORREF transColor =
TX_BLACK,
double xSource = 0,
double ySource = 0);
3007 bool txAlphaBlend (HDC destImage,
double xDest,
double yDest,
double width,
double height,
3008 HDC sourceImage,
double xSource = 0,
double ySource = 0,
double alpha = 1.0);
3030 double xSource = 0,
double ySource = 0,
double alpha = 1.0);
3407 #if defined (_TX_CPP11)
3408 template <
int txFramesToAverage = 5>
3410 const int txFramesToAverage = 5;
3415 double txGetFPS (
int minFrames = txFramesToAverage) tx_nodiscard;
3571 #ifdef FOR_DOXYGEN_ONLY
3572 inline Mouse& txCatchMouse (
bool shouldEat =
true);
3800 bool txPlaySound (const
char filename[] = NULL, DWORD mode = SND_ASYNC);
3862 int txSpeak (const
char* text, ...) tx_printfy (1);
3983 intptr_t
txPlayVideo (
int x,
int y,
int width,
int height, const
char fileName[],
3984 double zoom = 0,
double gain = 1, HWND wnd =
txWindow());
4103 #ifdef FOR_DOXYGEN_ONLY
4104 bool txNotifyIcon (
unsigned flags,
const char title[],
const char format[], ...) tx_printfy (3);
4214 #if defined (_TX_CPP11) || defined (FOR_DOXYGEN_ONLY)
4216 template <
typename T,
typename... ArgsT>
4217 int txPrintf (
const char* format, ArgsT... args);
4219 #define TX_PRINTF(...) ( _txPrintfCheck (__VA_ARGS__), txPrintf (__VA_ARGS__) )
4225 #if defined (_TX_CPP11) && !defined (FOR_DOXYGEN_ONLY)
4227 enum width_t :
int {};
4228 enum precision_t :
int {};
4230 inline width_t width (
int width) {
return (width_t) width; }
4231 inline precision_t precision (
int prec) {
return (precision_t) prec; }
4256 #if defined (_TX_CPP11) || defined (FOR_DOXYGEN_ONLY)
4258 template <
typename T,
typename... ArgsT>
4259 int txPrintf (std::ostringstream& stream,
const char* format, ArgsT... args);
4285 #if defined (_TX_CPP11) || defined (FOR_DOXYGEN_ONLY)
4287 template <
typename T,
typename... ArgsT>
4288 int txPrintf (
char buffer[],
size_t size,
const char* format, ArgsT... args);
4312 #if defined (_TX_CPP11) || defined (FOR_DOXYGEN_ONLY)
4314 template <
typename... ArgsT>
4315 std::string txFormat (
const char* format, ArgsT... args);
4394 #define sizearr( arr ) ( sizeof (get_size_of_an_array_with_unknown_or_nonconst_size_ (arr)) )
4399 template <
typename T,
size_t N> char (&get_size_of_an_array_with_unknown_or_nonconst_size_ (T (&) [N])) [N];
4403 #if defined (_TX_CPP11_MSVC15)
4404 template <
typename T,
size_t N> constexpr
size_t countof (
const T (&) [N] ) {
return N; }
4409 #define SIZEARR( arr ) ( sizeof (arr) / sizeof ((arr)[0]) )
4462 inline double random (
double left,
double right) tx_nodiscard tx_deprecated;
4464 inline double random (std::nomeow_t,
double left,
double right) tx_nodiscard;
4498 template <
typename Tx,
typename Ta,
typename Tb>
4499 inline bool In (Tx x, Ta a, Tb b) tx_nodiscard tx_deprecated;
4501 template <
typename Tx,
typename Ta,
typename Tb>
4502 inline bool In (std::nomeow_t, Tx x, Ta a, Tb b) tx_nodiscard tx_deprecated;
4553 inline bool In (
const POINT& pt,
const RECT& rect) tx_nodiscard tx_deprecated;
4554 inline bool In (
const COORD& pt,
const SMALL_RECT& rect) tx_nodiscard tx_deprecated;
4558 inline bool In (std::nomeow_t,
const POINT& pt,
const RECT& rect) tx_nodiscard tx_deprecated;
4559 inline bool In (std::nomeow_t,
const COORD& pt,
const SMALL_RECT& rect) tx_nodiscard tx_deprecated;
4582 #define MAX( a, b ) ( ((a) > (b))? (a) : (b) )
4584 template <
typename T>
4585 T
max (
const T& a,
const T& b) {
return (a > b)? a : b; }
4608 #define MIN( a, b ) ( ((a) < (b))? (a) : (b) )
4610 template <
typename T>
4611 T
min (
const T& a,
const T& b) {
return (a < b)? a : b; }
4629 #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
4631 #define ROUND( x ) ( (long) round (x) )
4635 #define ROUND( x ) ( (long) floor ((x) + 0.5) )
4673 const double txPI = asin (1.0) * 2;
4706 double sqr = pow (sqrt (x) * sqrt (x), sqrt (4.0));
4708 char str[1024] =
"";
4709 _snprintf_s (str,
sizeof (str),
"Возведение дало %g!" "!!" "!!" " Вы рады??1!!", sqr);
4710 txMessageBox (str,
"Получен ОТВЕТ!" "!!", MB_ICONEXCLAMATION | MB_YESNO) != IDCANCEL ||
4712 txMessageBox (
"Жаль...",
"А я так старалась , MB_ICONINFORMATION),
txMessageBox ("Уйду я от вас", "Злые вы...", MB_ICONSTOP),
exit (EXIT_FAILURE), 0 //-V2509 //-V2014
);
txNotifyIcon (1, NULL, "\n%s\n", "Высшая математика! \0" // А как это работает, а? //-V111
"С ума сойти... \0" //
"а КЭП подтверждает \0" // и кто это будет
"Главное - отчитаться\0" // поддерживать?..
"Невероятно, но факт \0"
"Кто бы мог подумать?\0" + GetTickCount() % 6 * 21);
return sqr; // Все же вернем значение. Мы же не звери
}
//{----------------------------------------------------------------------------------------------------------------
//! @ingroup Misc
//! @brief <i>Ну просто <b>очень, MB_ICONINFORMATION),
4713 txMessageBox (
"Уйду я от вас , "Злые вы...", MB_ICONSTOP),
exit (EXIT_FAILURE), 0 //-V2509 //-V2014
);
txNotifyIcon (1, NULL, "\n%s\n", "Высшая математика! \0" // А как это работает, а? //-V111
"С ума сойти... \0" //
"а КЭП подтверждает \0" // и кто это будет
"Главное - отчитаться\0" // поддерживать?..
"Невероятно, но факт \0"
"Кто бы мог подумать?\0" + GetTickCount() % 6 * 21);
return sqr; // Все же вернем значение. Мы же не звери
}
//{----------------------------------------------------------------------------------------------------------------
//! @ingroup Misc
//! @brief <i>Ну просто <b>очень, "Злые вы...", MB_ICONSTOP),
4714 exit (EXIT_FAILURE), 0
4717 txNotifyIcon (1, NULL,
"\n%s\n",
"Высшая математика! \0"
4719 "а КЭП подтверждает \0"
4720 "Главное - отчитаться\0"
4721 "Невероятно, но факт \0"
4722 "Кто бы мог подумать?\0" + GetTickCount() % 6 * 21);
4751 #ifdef FOR_DOXYGEN_ONLY
4752 #define _TX_DESTROY_3D
4755 #if defined (_TX_DESTROY_3D)
4783 #if defined (_MSC_VER) && !defined (_CLANG_VER)
4811 #define ZERO( type ) zero <type> ()
4814 template <
typename T>
inline T zero() tx_nodiscard;
4847 #define tx_auto_func( func ) _tx_auto_fun1 ( __LINE__, func )
4848 #define _tx_auto_fun1( n, func ) _tx_auto_fun2 ( n, func )
4849 #define _tx_auto_fun2( n, func ) auto _tx_auto_func_##n = _tx_auto_func ([&]() { func; })
4851 #define tx_finally(...) tx_auto_func (__VA_ARGS__)
4853 template <
typename T>
4867 template <
typename T>
4922 #if !defined (NDEBUG)
4924 #define TX_ASSERT( cond ) _txNOP ( !(cond)? (TX_ERROR ("\a" "ВНЕЗАПНО: Логическая ошибка: " \
4925 "Неверно, что \"%s\"." TX_COMMA #cond), 1/(int)!!(cond)) : 1 )
4928 #define TX_ASSERT( cond ) ((void) 1)
4936 #define assert( cond ) TX_ASSERT (cond)
4967 #if !defined (NDEBUG)
4968 #define asserted || TX_ERROR ("\a" "Обнаружен нулевой или ложный результат.")
4971 #define asserted || _txNOP (0)
4975 #define verified asserted
4978 #define TX_NEEDED asserted
5011 #if !defined (NDEBUG)
5013 #define verify assert
5017 #define verify( expr ) ( expr )
5042 #if !defined (FOR_DOXYGEN_ONLY)
5043 #define TX_ERROR( ... ) ::TX::_txError (__FILE__, __LINE__, __TX_FUNCTION__, 0, ##__VA_ARGS__)
5045 #define TX_ERROR( msg ) ::TX::_txError (__FILE__, __LINE__, __TX_FUNCTION__, 0, msg)
5049 #define TX_THROW TX_ERROR
5070 #if !defined (NDEBUG)
5071 #define TX_DEBUG_ERROR(...) TX_ERROR (__VA_ARGS__)
5074 #define TX_DEBUG_ERROR(...) ((void) 0)
5100 #ifdef FOR_DOXYGEN_ONLY
5101 void txDump (
const void* address,
const char name[] =
"_txDump()",
bool pause =
true);
5107 #define txDump( ... ) _txDump ((const void*)(uintptr_t) __VA_ARGS__)
5109 #define txDump( address, ... ) _txDump ((const void*)(uintptr_t) (address), #address, ##__VA_ARGS__)
5112 void _txDump (
const void* address,
const char name[] =
"_txDump()",
bool pause =
true);
5144 #define txStackBackTrace() _txStackBackTrace (__FILE__, __LINE__, __TX_FUNCTION__, true);
5172 char*
txDemangle (
const char* mangledName, std::nomeow_t);
5174 #define txTypename(value) txDemangle (typeid (value) .name()) .c_str()
5206 int txRegQuery (
const char* keyName,
const char* valueName,
void* value,
size_t szValue);
5291 #ifdef FOR_DOXYGEN_ONLY
5293 #define TX_DLLIMPORT( required, libName, retValType, funcName, funcParams, callType )
5299 #define TX_DLLIMPORT( required, libName, retValType, funcName, funcParams, ... ) \
5300 retValType (__VA_ARGS__* funcName) funcParams = (retValType (__VA_ARGS__*) funcParams) \
5301 _txDllImport ((libName), #funcName, (required))
5515 template <
typename T>
inline T
txUnlock (T value);
5545 #define txGDI( command, dc ) ( ((dc) == txDC())? txUnlock ( (txLock(), (command)) ) : (command) )
5572 #ifndef FOR_DOXYGEN_ONLY
5577 const char _TX_LOCALE[] =
"Russian";
5579 const char _TX_LOCALE[] =
"ru_RU.CP1251";
5582 const wchar_t _TX_WLOCALE[] = L
"Russian_Russia.ACP";
5586 int txSetLocale (
int codepage =
_TX_CODEPAGE,
const char locale[] = _TX_LOCALE,
const wchar_t wLocale[] = _TX_WLOCALE);
5603 int txPause (
const char* message, ...) tx_printfy (1);
5668 #if defined (_TX_NOINIT)
5671 #define _TX_NOINIT 1
5675 #define _TX_NOINIT 0
5725 #if !defined (TX_CONSOLE_MODE)
5727 #define TX_CONSOLE_MODE SW_HIDE
5737 #if !defined (TX_CONSOLE_FONT)
5739 #define TX_CONSOLE_FONT "Lucida Console"
5802 #ifdef FOR_DOXYGEN_ONLY
5813 #if defined (_TX_ALLOW_TRACE)
5817 #if defined (TX_TRACE)
5821 #if defined (_TX_USE_DEVPARTNER)
5872 HDC src,
int xSrc,
int ySrc,
int wSrc,
int hSrc, DWORD rOp) = NULL;
5876 extern bool (*
_txSwapBuffers) (HDC dest,
int xDest,
int yDest,
int wDest,
int hDest,
5877 HDC src,
int xSrc,
int ySrc,
int wSrc,
int hSrc, DWORD rOp);
5895 #if !defined (_TX_EXCEPTIONS_LIMIT)
5896 #define _TX_EXCEPTIONS_LIMIT 16
5899 #if !defined (_TX_FATAL_EXCEPTIONS_LIMIT)
5900 #define _TX_FATAL_EXCEPTIONS_LIMIT 16
5908 #ifdef FOR_DOXYGEN_ONLY
5909 #define _TX_FULL_STACKTRACE
5941 #if !defined (_TX_WAITABLE_PARENTS)
5942 #define _TX_WAITABLE_PARENTS "Winpty-agent.exe:Clion.exe, " \
5943 "Winpty-agent.exe:Clion64.exe, " \
5944 "starter.exe:eclipse.exe, " \
5945 "starter.exe:javaw.exe, " \
5946 "cmd.exe:devenv.exe, " \
5947 "VSDebugConsole.exe:devenv.exe, " \
5948 "VSDebugConsole.exe:msvsmon.exe, " \
5949 "consolepauser.exe:devcpp.exe, " \
5950 "cb_console_runner.exe:codeblocks.exe"
5974 #if !defined (_TX_ALLOW_KILL_PARENT)
5975 #define _TX_ALLOW_KILL_PARENT true
6070 #ifdef FOR_DOXYGEN_ONLY
6129 #ifdef FOR_DOXYGEN_ONLY
6130 #define _TX_ALLOW_TRACE
6165 #ifdef FOR_DOXYGEN_ONLY
6169 #if !defined (TX_TRACE)
6170 #define TX_TRACE { if (_txLoc::Cur.trace) _txTrace (__FILE__, __LINE__, __TX_FUNCTION__); }
6174 void _txTrace (
const char file[],
int line,
const char func[],
const char msg[] = NULL, ...);
6181 #ifndef FOR_DOXYGEN_ONLY
6194 static _txLoc _tx_thread Cur;
6199 typedef _txFuncEntry this_t;
6203 _txFuncEntry() : loc (_txLoc::Cur) { _txLoc::Cur.inTX++; _txLoc::Cur.prev = &loc; }
6204 void restore() { _txLoc::Cur = loc; }
6205 ~_txFuncEntry() { restore(); }
6208 _txFuncEntry (
const this_t&) _tx_delete;
6209 this_t& operator = (
const this_t&) _tx_delete;
6212 #if defined (_GCC_VER)
6214 inline const char* __txLocCurSet (
const char* _file,
int _line,
const char* _func)
6215 { _txLoc::Cur.file = _file; _txLoc::Cur.line = _line; _txLoc::Cur.func = _func;
return _func; }
6219 #define __txLocCurSet( _file, _line, _func ) \
6220 ( _txLoc::Cur.file = (_file), _txLoc::Cur.line = (_line), _txLoc::Cur.func = (_func) )
6224 #define _txLocCurSet() __txLocCurSet (__FILE__, __LINE__, __TX_FUNCTION__)
6226 #define _txLocLvlSet(lvl) { _txLoc::Cur.trace = (lvl); }
6281 #if defined (_TX_ALLOW_TRACE)
6283 #define _txEntry(lvl) _txFuncEntry __txFuncEntry; { if (lvl) _txLocLvlSet (lvl); $; }
6285 #define $ { _txLocCurSet(); if (_txLoc::Cur.trace <= _TX_ALLOW_TRACE+0) { TX_TRACE; } }
6287 #define $$ { __txFuncEntry.restore(); }
6289 #elif defined (_DEBUG)
6291 #define _txEntry(lvl) _txFuncEntry __txFuncEntry; { $; }
6293 #define $ { _txLocCurSet(); }
6295 #define $$ { __txFuncEntry.restore(); }
6299 #define _txEntry(lvl) ;
6307 #define $0 _txEntry (0)
6308 #define $1 _txEntry (1)
6309 #define $2 _txEntry (2)
6310 #define $3 _txEntry (3)
6311 #define $4 _txEntry (4)
6312 #define $5 _txEntry (5)
6313 #define $6 _txEntry (6)
6314 #define $7 _txEntry (7)
6315 #define $8 _txEntry (8)
6316 #define $9 _txEntry (9)
6354 extern CRITICAL_SECTION _txCanvas_LockBackBuf;
6388 explicit txAutoLock (CRITICAL_SECTION* cs,
bool mandatory =
true) :
6391 $1
if (!
cs_)
return;
6393 if (mandatory) {$ EnterCriticalSection (
cs_); }
6394 else {$ TryEnterCriticalSection (
cs_)? 0 : (
cs_ = NULL); }
6415 $1
new (
this)
txAutoLock (&_txCanvas_LockBackBuf, mandatory);
6424 $1
if (!
cs_)
return;
6425 $ LeaveCriticalSection (
cs_);
cs_ = NULL;
6433 operator bool ()
const
6435 $1
return (
cs_ != NULL);
6518 END = (
int) 0x00000000
6625 virtual int dialogProc (HWND _wnd, UINT _msg, WPARAM _wParam, LPARAM _lParam);
6677 static intptr_t CALLBACK
DialogProc_ (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);
6719 #define TX_BEGIN_MESSAGE_MAP() \
6720 virtual int dialogProc (HWND _wnd, UINT _msg, WPARAM _wParam, LPARAM _lParam) _tx_override \
6722 int _result = txDialog::dialogProc (_wnd, _msg, _wParam, _lParam); (void) _result; \
6749 #define TX_HANDLE( id ) \
6775 #define TX_COMMAND_MAP \
6779 if (_msg == WM_COMMAND) switch (LOWORD (_wParam)) \
6804 #define TX_END_MESSAGE_MAP \
6842 const char*
txInputBox (
const char* text = NULL,
const char* caption = NULL,
const char* input = NULL) tx_nodiscard;
6846 const char*
txInputBox (
const char* text,
const char* caption,
const char* input)
6853 if (!text) text =
"Введите строку:";
6855 if (!input) input =
"";
6865 #define ID_TEXT_ 101
6866 #define ID_INPUT_ 102
6885 {
txDialog::EDIT, input, ID_INPUT_, 10, 60, 220, 15, ES_LEFT | WS_BORDER | ES_AUTOHSCROLL | WS_TABSTOP },
6886 {
txDialog::BUTTON,
"&OK", IDOK, 180, 10, 50, 15, BS_DEFPUSHBUTTON | WS_TABSTOP },
6887 {
txDialog::BUTTON,
"&Cancel", IDCANCEL, 180, 30, 50, 15, BS_PUSHBUTTON | WS_TABSTOP },
6920 TX_HANDLE (IDOK) GetDlgItemText (_wnd, ID_INPUT_, str,
sizeof (str) - 1);
6943 static inputDlg dlg;
6949 dlg.dialogBox (layout);
6985 #if defined (_MSC_VER)
6986 #pragma warning (push, 3)
6988 #pragma warning (disable: 4365)
6989 #pragma warning (disable: 4005)
6992 #if defined (__STRICT_ANSI__) && defined (__STRICT_ANSI__UNDEFINED)
6993 #undef __STRICT_ANSI__
7001 #include <process.h>
7010 #include <exception>
7011 #include <stdexcept>
7013 #include <tlhelp32.h>
7014 #include <shellapi.h>
7016 #if defined (_GCC_VER)
7025 #if defined (__CYGWIN__)
7029 #include <termios.h>
7033 #if defined (_MSC_VER)
7038 #include <ntstatus.h>
7041 #include <dbghelp.h>
7045 #if defined (_GCC_VER) || defined (_MSC_VER) && (_MSC_VER >= 1800)
7046 #include <inttypes.h>
7051 #if defined (TX_USE_SPEAK)
7057 #if defined (_MSC_VER)
7058 #pragma warning (pop)
7061 #if defined (__STRICT_ANSI__UNDEFINED)
7062 #define __STRICT_ANSI__
7089 #ifndef AC_SRC_ALPHA
7090 #define AC_SRC_ALPHA 0x01
7093 #ifndef SMTO_ERRORONEXIT
7094 #define SMTO_ERRORONEXIT 0x0020
7097 #ifndef NT_CONSOLE_PROPS_SIG
7098 #define NT_CONSOLE_PROPS_SIG 0xA0000002
7102 #define NIIF_INFO 0x00000001
7103 #define NIIF_WARNING 0x00000002
7104 #define NIIF_ERROR 0x00000003
7108 #define NIF_STATE 0x00000008
7109 #define NIF_INFO 0x00000010
7112 #ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
7113 #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004
7116 #ifndef SYMOPT_CASE_INSENSITIVE
7117 #define SYMOPT_CASE_INSENSITIVE 0x00000001
7118 #define SYMOPT_UNDNAME 0x00000002
7119 #define SYMOPT_DEFERRED_LOADS 0x00000004
7120 #define SYMOPT_NO_CPP 0x00000008
7121 #define SYMOPT_LOAD_LINES 0x00000010
7122 #define SYMOPT_OMAP_FIND_NEAREST 0x00000020
7123 #define SYMOPT_LOAD_ANYTHING 0x00000040
7124 #define SYMOPT_IGNORE_CVREC 0x00000080
7125 #define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100
7126 #define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200
7127 #define SYMOPT_EXACT_SYMBOLS 0x00000400
7128 #define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800
7129 #define SYMOPT_IGNORE_NT_SYMPATH 0x00001000
7130 #define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000
7131 #define SYMOPT_PUBLICS_ONLY 0x00004000
7132 #define SYMOPT_NO_PUBLICS 0x00008000
7133 #define SYMOPT_AUTO_PUBLICS 0x00010000
7134 #define SYMOPT_NO_IMAGE_SEARCH 0x00020000
7135 #define SYMOPT_SECURE 0x00040000
7136 #define SYMOPT_NO_PROMPTS 0x00080000
7137 #define SYMOPT_ALLOW_ZERO_ADDRESS 0x01000000
7138 #define SYMOPT_DISABLE_SYMSRV_AUTODETECT 0x02000000
7139 #define SYMOPT_FAVOR_COMPRESSED 0x00800000
7140 #define SYMOPT_FLAT_DIRECTORY 0x00400000
7141 #define SYMOPT_IGNORE_IMAGEDIR 0x00200000
7142 #define SYMOPT_OVERWRITE 0x00100000
7143 #define SYMOPT_DEBUG 0x80000000
7148 #ifndef STATUS_POSSIBLE_DEADLOCK
7149 #define STATUS_POSSIBLE_DEADLOCK 0xC0000194
7152 #ifndef STATUS_FLOAT_MULTIPLE_FAULTS
7153 #define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4
7156 #ifndef STATUS_STACK_BUFFER_OVERRUN
7157 #define STATUS_STACK_BUFFER_OVERRUN 0xC0000409
7160 #ifndef STATUS_ASSERTION_FAILURE
7161 #define STATUS_ASSERTION_FAILURE 0xC0000420
7164 #ifndef STATUS_WX86_BREAKPOINT
7165 #define STATUS_WX86_BREAKPOINT 0x4000001F
7168 #ifndef DBG_PRINTEXCEPTION_C
7169 #define DBG_PRINTEXCEPTION_C 0x40010006
7172 #ifndef DBG_PRINTEXCEPTION_WIDE_C
7173 #define DBG_PRINTEXCEPTION_WIDE_C 0x4001000A
7176 #ifndef DBG_THREAD_NAME
7177 #define DBG_THREAD_NAME 0x406D1388
7180 #define EXCEPTION_CPP_MSC 0xE06D7363
7181 #define EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER1 0x19930520
7182 #define EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER2 0x19930521
7183 #define EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER3 0x19930522
7184 #define EXCEPTION_CPP_MSC_EH_PURE_MAGIC_NUMBER1 0x01994000
7186 #define EXCEPTION_CPP_GCC 0x20474343
7187 #define EXCEPTION_CPP_GCC_UNWIND 0x21474343
7188 #define EXCEPTION_CPP_GCC_FORCED 0x22474343
7190 #define EXCEPTION_CLR_FAILURE 0xE0434f4D
7192 #define EXCEPTION_CPP_BORLAND_BUILDER 0x0EEDFAE6
7193 #define EXCEPTION_CPP_BORLAND_DELPHI 0x0EEDFADE
7195 #pragma pack (push, 1)
7197 struct CONSOLE_CURSOR_INFO
7203 struct CONSOLE_FONT_INFO
7209 struct CONSOLE_FONT_INFOEX
7216 WCHAR FaceName[LF_FACESIZE];
7219 struct DATABLOCK_HEADER
7225 struct NT_CONSOLE_PROPS
7227 DATABLOCK_HEADER dbh;
7229 WORD wFillAttribute;
7230 WORD wPopupFillAttribute;
7231 COORD dwScreenBufferSize;
7233 COORD dwWindowOrigin;
7235 DWORD nInputBufferSize;
7239 WCHAR FaceName[LF_FACESIZE];
7245 UINT uHistoryBufferSize;
7246 UINT uNumberOfHistoryBuffers;
7249 COLORREF ColorTable[16];
7263 TBPF_NOPROGRESS = 0x0,
7264 TBPF_INDETERMINATE = 0x1,
7272 const GUID IID_IShellLink = {0x000214ee, 0x0000, 0x0000, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
7273 const GUID IID_IShellLinkDataList = {0x45e2b4ae, 0xb1c3, 0x11d0, {0xb9,0x2f,0x00,0xa0,0xc9,0x03,0x12,0xe1}};
7274 const GUID IID_IPersistFile = {0x0000010b, 0x0000, 0x0000, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
7276 const GUID IID_ITaskbarList3 = {0xea1afb91, 0x9e28, 0x4b86, {0x90,0xe9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf}};
7277 const GUID CLSID_TaskbarList = {0x56fdf344, 0xfd6d, 0x11d0, {0x95,0x8a,0x00,0x60,0x97,0xc9,0xa0,0x90}};
7279 const GUID CLSID_SpVoice = {0x96749377, 0x3391, 0x11d2, {0x9e,0xe3,0x00,0xc0,0x4f,0x79,0x73,0x96}};
7280 const GUID IID_ISpVoice = {0x6c44df74, 0x72b9, 0x4992, {0xa1,0xec,0xef,0x99,0x6e,0x04,0x22,0xd4}};
7282 typedef DWORD NTSTATUS;
7283 typedef ULONG_PTR KAFFINITY;
7284 typedef LONG KPRIORITY;
7286 struct UNICODE_STRING
7289 USHORT MaximumLength;
7293 struct RTL_DRIVE_LETTER_CURDIR
7298 UNICODE_STRING DosPath;
7303 UNICODE_STRING DosPath;
7307 struct RTL_USER_PROCESS_PARAMETERS
7309 ULONG AllocationSize;
7313 HANDLE ConsoleHandle;
7318 CURDIR CurrentDirectory;
7319 UNICODE_STRING DllPath;
7320 UNICODE_STRING ImagePathName;
7321 UNICODE_STRING CommandLine;
7322 wchar_t* Environment;
7327 ULONG dwXCountChars;
7328 ULONG dwYCountChars;
7329 ULONG dwFillAttribute;
7332 UNICODE_STRING WindowTitle;
7333 UNICODE_STRING Desktop;
7334 UNICODE_STRING ShellInfo;
7335 UNICODE_STRING RuntimeInfo;
7336 RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
7346 RTL_USER_PROCESS_PARAMETERS* ProcessParameters;
7348 void* AtlThunkSListPtr;
7353 ULONG AtlThunkSListPtr32;
7354 void* Reserved9[45];
7355 BYTE Reserved10[96];
7356 void* PostProcessInitRoutine;
7357 BYTE Reserved11[128];
7358 void* Reserved12[1];
7364 void* Reserved1[12];
7365 PEB* ProcessEnvironmentBlock;
7366 void* Reserved2[399];
7367 BYTE Reserved3[1952];
7370 void* Reserved5[26];
7371 void* ReservedForOle;
7373 void* TlsExpansionSlots;
7376 struct PROCESS_BASIC_INFORMATION
7378 NTSTATUS ExitStatus;
7379 PEB* PebBaseAddress;
7380 KAFFINITY AffinityMask;
7381 KPRIORITY BasePriority;
7382 ULONG_PTR UniqueProcessId;
7383 ULONG_PTR InheritedFromUniqueProcessId;
7404 DWORD ThCallbackStack;
7405 DWORD ThCallbackBStore;
7408 DWORD64 KiCallUserMode;
7409 DWORD64 KeUserCallbackDispatcher;
7410 DWORD64 SystemRangeStart;
7411 DWORD64 KiUserExceptionDispatcher;
7414 DWORD64 Reserved[5];
7420 ADDRESS64 AddrReturn;
7421 ADDRESS64 AddrFrame;
7422 ADDRESS64 AddrStack;
7423 ADDRESS64 AddrBStore;
7424 void* FuncTableEntry;
7428 DWORD64 Reserved[3];
7432 struct WOW64_FLOATING_SAVE_AREA
7438 DWORD ErrorSelector;
7441 BYTE RegisterArea[80];
7445 #pragma pack (push, 4)
7447 struct WOW64_CONTEXT
7458 WOW64_FLOATING_SAVE_AREA FloatSave;
7479 BYTE ExtendedRegisters[512];
7488 ULONG64 Reserved[2];
7503 struct IMAGEHLP_LINE64
7512 typedef bool (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64) (HANDLE process, DWORD64 baseAddress,
void* buffer, DWORD size, DWORD* bytesRead);
7513 typedef void* (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64) (HANDLE process, DWORD64 baseAddress);
7514 typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64) (HANDLE process, DWORD64 address);
7515 typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64) (HANDLE process, HANDLE thread, ADDRESS64* address);
7517 typedef void (*unexpected_handler)();
7519 #pragma pack (push, 4)
7521 struct MINIDUMP_THREAD_CALLBACK
7524 HANDLE ThreadHandle;
7526 ULONG SizeOfContext;
7531 struct MINIDUMP_THREAD_EX_CALLBACK
7534 HANDLE ThreadHandle;
7536 ULONG SizeOfContext;
7539 ULONG64 BackingStoreBase;
7540 ULONG64 BackingStoreEnd;
7543 struct MINIDUMP_MODULE_CALLBACK
7546 ULONG64 BaseOfImage;
7549 ULONG TimeDateStamp;
7550 VS_FIXEDFILEINFO VersionInfo;
7552 ULONG SizeOfCvRecord;
7554 ULONG SizeOfMiscRecord;
7557 struct MINIDUMP_INCLUDE_THREAD_CALLBACK
7562 struct MINIDUMP_INCLUDE_MODULE_CALLBACK
7564 ULONG64 BaseOfImage;
7567 struct MINIDUMP_MEMORY_INFO
7569 ULONG64 BaseAddress;
7570 ULONG64 AllocationBase;
7571 ULONG32 AllocationProtect;
7572 ULONG32 __alignment1;
7577 ULONG32 __alignment2;
7580 struct MINIDUMP_USER_STREAM
7587 struct MINIDUMP_USER_STREAM_INFORMATION
7589 ULONG UserStreamCount;
7590 MINIDUMP_USER_STREAM* UserStreamArray;
7593 struct MINIDUMP_CALLBACK_INPUT
7596 HANDLE ProcessHandle;
7601 MINIDUMP_THREAD_CALLBACK Thread;
7602 MINIDUMP_THREAD_EX_CALLBACK ThreadEx;
7603 MINIDUMP_MODULE_CALLBACK Module;
7604 MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread;
7605 MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule;
7609 struct MINIDUMP_CALLBACK_OUTPUT
7613 ULONG ModuleWriteFlags;
7614 ULONG ThreadWriteFlags;
7615 ULONG SecondaryFlags;
7625 unsigned CheckCancel;
7634 MINIDUMP_MEMORY_INFO VmRegion;
7641 struct MINIDUMP_EXCEPTION_INFORMATION
7644 EXCEPTION_POINTERS* ExceptionPointers;
7645 unsigned ClientPointers;
7648 typedef int (WINAPI* MINIDUMP_CALLBACK_ROUTINE) (
void* param, MINIDUMP_CALLBACK_INPUT* input, MINIDUMP_CALLBACK_OUTPUT* output);
7650 struct MINIDUMP_CALLBACK_INFORMATION
7652 MINIDUMP_CALLBACK_ROUTINE CallbackRoutine;
7653 void* CallbackParam;
7658 MiniDumpNormal = 0x00000000,
7659 MiniDumpWithDataSegs = 0x00000001,
7660 MiniDumpWithFullMemory = 0x00000002,
7661 MiniDumpWithHandleData = 0x00000004,
7662 MiniDumpFilterMemory = 0x00000008,
7663 MiniDumpScanMemory = 0x00000010,
7664 MiniDumpWithUnloadedModules = 0x00000020,
7665 MiniDumpWithIndirectlyReferencedMemory = 0x00000040,
7666 MiniDumpFilterModulePaths = 0x00000080,
7667 MiniDumpWithProcessThreadData = 0x00000100,
7668 MiniDumpWithPrivateReadWriteMemory = 0x00000200,
7669 MiniDumpWithoutOptionalData = 0x00000400,
7670 MiniDumpWithFullMemoryInfo = 0x00000800,
7671 MiniDumpWithThreadInfo = 0x00001000,
7672 MiniDumpWithCodeSegs = 0x00002000,
7673 MiniDumpWithoutAuxiliaryState = 0x00004000,
7674 MiniDumpWithFullAuxiliaryState = 0x00008000,
7675 MiniDumpWithPrivateWriteCopyMemory = 0x00010000,
7676 MiniDumpIgnoreInaccessibleMemory = 0x00020000,
7677 MiniDumpWithTokenInformation = 0x00040000
7681 #define CONTEXT_ALL ( CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS )
7690 #define FOREGROUND_BLACK ( 0 )
7691 #define FOREGROUND_CYAN ( FOREGROUND_BLUE | FOREGROUND_GREEN )
7692 #define FOREGROUND_MAGENTA ( FOREGROUND_BLUE | FOREGROUND_RED )
7693 #define FOREGROUND_DARKYELLOW ( FOREGROUND_GREEN | FOREGROUND_RED )
7694 #define FOREGROUND_LIGHTGRAY ( FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED )
7695 #define FOREGROUND_DARKGRAY ( FOREGROUND_INTENSITY )
7696 #define FOREGROUND_LIGHTBLUE ( FOREGROUND_BLUE | FOREGROUND_INTENSITY )
7697 #define FOREGROUND_LIGHTGREEN ( FOREGROUND_GREEN | FOREGROUND_INTENSITY )
7698 #define FOREGROUND_LIGHTCYAN ( FOREGROUND_CYAN | FOREGROUND_INTENSITY )
7699 #define FOREGROUND_LIGHTRED ( FOREGROUND_RED | FOREGROUND_INTENSITY )
7700 #define FOREGROUND_LIGHTMAGENTA ( FOREGROUND_MAGENTA | FOREGROUND_INTENSITY )
7701 #define FOREGROUND_YELLOW ( FOREGROUND_DARKYELLOW | FOREGROUND_INTENSITY )
7702 #define FOREGROUND_WHITE ( FOREGROUND_LIGHTGRAY | FOREGROUND_INTENSITY )
7704 #define BACKGROUND_BLACK ( 0 )
7705 #define BACKGROUND_CYAN ( BACKGROUND_BLUE | BACKGROUND_GREEN )
7706 #define BACKGROUND_MAGENTA ( BACKGROUND_BLUE | BACKGROUND_RED )
7707 #define BACKGROUND_DARKYELLOW ( BACKGROUND_GREEN | BACKGROUND_RED )
7708 #define BACKGROUND_GRAY ( BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED )
7709 #define BACKGROUND_DARKGRAY ( BACKGROUND_INTENSITY )
7710 #define BACKGROUND_LIGHTBLUE ( BACKGROUND_BLUE | BACKGROUND_INTENSITY )
7711 #define BACKGROUND_LIGHTGREEN ( BACKGROUND_GREEN | BACKGROUND_INTENSITY )
7712 #define BACKGROUND_LIGHTCYAN ( BACKGROUND_CYAN | BACKGROUND_INTENSITY )
7713 #define BACKGROUND_LIGHTRED ( BACKGROUND_RED | BACKGROUND_INTENSITY )
7714 #define BACKGROUND_LIGHTMAGENTA ( BACKGROUND_MAGENTA | BACKGROUND_INTENSITY )
7715 #define BACKGROUND_LIGHTYELLOW ( BACKGROUND_DARKYELLOW | BACKGROUND_INTENSITY )
7716 #define BACKGROUND_WHITE ( BACKGROUND_DARKGRAY | BACKGROUND_INTENSITY )
7728 #if defined (_MSC_VER)
7732 #pragma pack (push, 4)
7738 __int32 pForwardCompat;
7739 __int32 pCatchableTypeArray;
7742 struct CatchableTypeArray
7744 __int32 nCatchableTypes;
7745 __int32 arrayOfCatchableTypes[];
7748 struct CatchableType
7752 __int32 thisDisplacement[3];
7753 __int32 sizeOrOffset;
7754 __int32 copyFunction;
7765 #define _TX_MSC__CXX_DETECT_RETHROW( exc ) \
7768 (exc) -> ExceptionCode == EXCEPTION_CPP_MSC && \
7769 (exc) -> NumberParameters >= 3 && \
7771 ((exc)-> ExceptionInformation[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER1 || \
7772 (exc)-> ExceptionInformation[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER2 || \
7773 (exc)-> ExceptionInformation[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER3) && \
7775 (exc) -> ExceptionInformation[2] == 0 \
7790 #if defined (_GCC_VER)
7797 struct __cxa_exception
7802 ::std::type_info* exceptionType;
7803 void (*exceptionDestructor)(
void*);
7807 __cxa_exception* primaryException;
7812 void (*unexpected_handler)();
7813 std::terminate_handler terminateHandler;
7815 __cxa_exception* nextException;
7817 int handlerSwitchValue;
7818 const unsigned char* actionRecord;
7819 const unsigned char* languageSpecificData;
7823 _Unwind_Exception unwindHeader;
7826 struct __cxa_eh_globals
7828 __cxa_exception* caughtExceptions;
7829 unsigned int uncaughtExceptions;
7835 extern "C" ABI::__cxa_eh_globals* __cxa_get_globals();
7851 #define _TX_DLLIMPORT( lib, retval, name, params ) TX_DLLIMPORT (true, lib ".dll", retval, name, params, WINAPI)
7852 #define _TX_DLLIMPORT_OPT( lib, retval, name, params ) TX_DLLIMPORT (false, lib ".dll", retval, name, params, WINAPI)
7853 #define _TX_DLLIMPORT_CRT( lib, retval, name, params ) TX_DLLIMPORT (false, lib ".dll", retval, name, params, please)
7855 void (*_txDllImport (
const char dllFileName[],
const char funcName[],
bool required =
true)) ();
7863 _TX_DLLIMPORT (
"GDI32", HDC, CreateCompatibleDC, (HDC dc));
7864 _TX_DLLIMPORT (
"GDI32", HBITMAP, CreateCompatibleBitmap, (HDC dc,
int width,
int height));
7865 _TX_DLLIMPORT (
"GDI32", HGDIOBJ, GetStockObject, (
int object));
7866 _TX_DLLIMPORT (
"GDI32", HGDIOBJ, SelectObject, (HDC dc, HGDIOBJ
object));
7867 _TX_DLLIMPORT (
"GDI32", HGDIOBJ, GetCurrentObject, (HDC dc,
unsigned objectType));
7868 _TX_DLLIMPORT (
"GDI32",
int, GetObjectA, (HGDIOBJ obj,
int bufsize,
void* buffer));
7869 _TX_DLLIMPORT (
"GDI32", DWORD, GetObjectType, (HGDIOBJ
object));
7870 _TX_DLLIMPORT (
"GDI32",
bool, DeleteDC, (HDC dc));
7871 _TX_DLLIMPORT (
"GDI32",
bool, DeleteObject, (HGDIOBJ
object));
7872 _TX_DLLIMPORT (
"GDI32", COLORREF, SetTextColor, (HDC dc, COLORREF color));
7873 _TX_DLLIMPORT (
"GDI32", COLORREF, SetBkColor, (HDC dc, COLORREF color));
7874 _TX_DLLIMPORT (
"GDI32",
int, SetBkMode, (HDC dc,
int bkMode));
7875 _TX_DLLIMPORT (
"GDI32", HFONT, CreateFontA, (
int height,
int width,
int escapement,
int orientation,
7876 int weight, DWORD italic, DWORD underline, DWORD strikeout,
7877 DWORD charSet, DWORD outputPrec, DWORD clipPrec,
7878 DWORD quality, DWORD pitchAndFamily,
const char face[]));
7879 _TX_DLLIMPORT (
"GDI32",
int, EnumFontFamiliesExA, (HDC dc, LPLOGFONT logFont, FONTENUMPROC enumProc,
7880 LPARAM lParam, DWORD reserved));
7881 _TX_DLLIMPORT (
"GDI32", COLORREF, SetPixel, (HDC dc,
int x,
int y, COLORREF color));
7882 _TX_DLLIMPORT (
"GDI32", COLORREF, GetPixel, (HDC dc,
int x,
int y));
7883 _TX_DLLIMPORT (
"GDI32", HPEN, CreatePen, (
int penStyle,
int width, COLORREF color));
7884 _TX_DLLIMPORT (
"GDI32", HBRUSH, CreateSolidBrush, (COLORREF color));
7885 _TX_DLLIMPORT (
"GDI32",
bool, MoveToEx, (HDC dc,
int x,
int y, POINT* point));
7886 _TX_DLLIMPORT (
"GDI32",
bool, LineTo, (HDC dc,
int x,
int y));
7887 _TX_DLLIMPORT (
"GDI32",
bool, Polygon, (HDC dc,
const POINT points[],
int count));
7888 _TX_DLLIMPORT (
"GDI32",
bool, Polyline, (HDC dc,
const POINT points[],
int count));
7889 _TX_DLLIMPORT (
"GDI32",
bool, PolyBezier, (HDC dc,
const POINT points[],
int count));
7890 _TX_DLLIMPORT (
"GDI32",
bool, Rectangle, (HDC dc,
int x0,
int y0,
int x1,
int y1));
7891 _TX_DLLIMPORT (
"GDI32",
bool, RoundRect, (HDC dc,
int x0,
int y0,
int x1,
int y1,
int sizeX,
int sizeY));
7892 _TX_DLLIMPORT (
"GDI32",
bool, Ellipse, (HDC dc,
int x0,
int y0,
int x1,
int y1));
7893 _TX_DLLIMPORT (
"GDI32",
bool, Arc, (HDC dc,
int x0,
int y0,
int x1,
int y1,
7894 int xStart,
int yStart,
int xEnd,
int yEnd));
7895 _TX_DLLIMPORT (
"GDI32",
bool, Pie, (HDC dc,
int x0,
int y0,
int x1,
int y1,
7896 int xStart,
int yStart,
int xEnd,
int yEnd));
7897 _TX_DLLIMPORT (
"GDI32",
bool, Chord, (HDC dc,
int x0,
int y0,
int x1,
int y1,
7898 int xStart,
int yStart,
int xEnd,
int yEnd));
7899 _TX_DLLIMPORT (
"GDI32",
bool, TextOutA, (HDC dc,
int x,
int y,
const char string[],
int length));
7900 _TX_DLLIMPORT (
"GDI32", UINT, SetTextAlign, (HDC dc,
unsigned mode));
7901 _TX_DLLIMPORT (
"GDI32",
bool, GetTextExtentPoint32A, (HDC dc,
const char string[],
int length, SIZE* size));
7902 _TX_DLLIMPORT (
"GDI32",
bool, ExtFloodFill, (HDC dc,
int x,
int y, COLORREF color,
unsigned type));
7903 _TX_DLLIMPORT (
"GDI32",
bool, BitBlt, (HDC dest,
int xDest,
int yDest,
int width,
int height,
7904 HDC src,
int xSrc,
int ySrc, DWORD rOp));
7905 _TX_DLLIMPORT (
"GDI32",
bool, StretchBlt, (HDC dest,
int xDest,
int yDest,
int width,
int height,
7906 HDC src,
int xSrc,
int ySrc,
int wSrc,
int hSrc, DWORD rOp));
7907 _TX_DLLIMPORT (
"GDI32",
bool, PlgBlt, (HDC dest,
const POINT* parallelogram,
7908 HDC src,
int xSrc,
int ySrc,
int width,
int height,
7909 HBITMAP mask,
int xMask,
int yMask));
7910 _TX_DLLIMPORT (
"GDI32",
int, SetDIBitsToDevice, (HDC dc,
int xDest,
int yDest, DWORD width, DWORD height,
7911 int xSrc,
int ySrc,
unsigned startLine,
unsigned numLines,
7912 const void* data,
const BITMAPINFO* info,
unsigned colorUse));
7913 _TX_DLLIMPORT (
"GDI32",
int, GetDIBits, (HDC hdc, HBITMAP hbmp,
unsigned uStartScan,
unsigned cScanLines,
7914 void* lpvBits, BITMAPINFO* lpbi,
unsigned usage));
7915 _TX_DLLIMPORT (
"GDI32",
bool, PatBlt, (HDC dc,
int x0,
int y0,
int width,
int height, DWORD rOp));
7916 _TX_DLLIMPORT (
"GDI32",
int, SetROP2, (HDC dc,
int mode));
7917 _TX_DLLIMPORT (
"GDI32",
int, SetStretchBltMode, (HDC dc,
int mode));
7918 _TX_DLLIMPORT (
"GDI32", DWORD, GdiSetBatchLimit, (DWORD limit));
7919 _TX_DLLIMPORT (
"GDI32", HBITMAP, CreateDIBSection, (HDC dc,
const BITMAPINFO* bmInfo,
unsigned colorUsage,
void **vBits,
7920 HANDLE section, DWORD offset));
7922 _TX_DLLIMPORT (
"User32",
int, DrawTextA, (HDC dc,
const char text[],
int length, RECT* rect,
unsigned format));
7923 _TX_DLLIMPORT (
"User32", HANDLE, LoadImageA, (HINSTANCE inst,
const char name[],
unsigned type,
7924 int sizex,
int sizey,
unsigned mode));
7925 _TX_DLLIMPORT_OPT (
"User32",
bool, IsHungAppWindow, (HWND wnd));
7926 _TX_DLLIMPORT_OPT (
"User32", HWND, GhostWindowFromHungWindow, (HWND wnd));
7927 _TX_DLLIMPORT_OPT (
"User32",
bool, FlashWindowEx, (
const FLASHWINFO* flash));
7929 _TX_DLLIMPORT (
"WinMM",
bool, PlaySound, (
const char sound[], HMODULE mod, DWORD mode));
7931 _TX_DLLIMPORT_OPT (
"MSImg32",
bool, TransparentBlt, (HDC dest,
int destX,
int destY,
int destWidth,
int destHeight,
7932 HDC src,
int srcX,
int srcY,
int srcWidth,
int srcHeight,
7933 unsigned transparentColor));
7934 _TX_DLLIMPORT_OPT (
"MSImg32",
bool, AlphaBlend, (HDC dest,
int destX,
int destY,
int destWidth,
int destHeight,
7935 HDC src,
int srcX,
int srcY,
int srcWidth,
int srcHeight,
7936 BLENDFUNCTION blending));
7938 _TX_DLLIMPORT (
"Kernel32",
void, ExitProcess, (
unsigned retcode));
7939 _TX_DLLIMPORT (
"Kernel32",
bool, TerminateProcess, (HANDLE process,
unsigned retcode));
7940 _TX_DLLIMPORT_OPT (
"Kernel32",
void, FatalExit, (
int retcode));
7941 _TX_DLLIMPORT_OPT (
"Kernel32",
void, FatalAppExitA, (
unsigned action,
const char message[]));
7942 _TX_DLLIMPORT_OPT (
"Kernel32", DWORD, GetThreadId, (HANDLE thread));
7943 _TX_DLLIMPORT (
"Kernel32", HWND, GetConsoleWindow, (
void));
7944 _TX_DLLIMPORT_OPT (
"Kernel32",
bool, SetConsoleFont, (HANDLE con, DWORD fontIndex));
7945 _TX_DLLIMPORT_OPT (
"Kernel32", DWORD, GetNumberOfConsoleFonts, (
void));
7946 _TX_DLLIMPORT_OPT (
"Kernel32",
bool, GetCurrentConsoleFont, (HANDLE con,
bool maxWnd, CONSOLE_FONT_INFO* curFont));
7947 _TX_DLLIMPORT_OPT (
"Kernel32",
bool, GetCurrentConsoleFontEx, (HANDLE con,
bool maxWnd, CONSOLE_FONT_INFOEX* curFont));
7948 _TX_DLLIMPORT_OPT (
"Kernel32",
bool, SetCurrentConsoleFontEx, (HANDLE con,
bool maxWnd, CONSOLE_FONT_INFOEX* curFont));
7949 _TX_DLLIMPORT_OPT (
"Kernel32",
void, RtlCaptureContext, (CONTEXT* contextRecord));
7950 _TX_DLLIMPORT_OPT (
"Kernel32", USHORT, RtlCaptureStackBackTrace, (DWORD framesToSkip, DWORD framesToCapture,
void** backTrace, DWORD* hash));
7951 _TX_DLLIMPORT_OPT (
"Kernel32",
void*, AddVectoredExceptionHandler, (
unsigned long firstHandler, PVECTORED_EXCEPTION_HANDLER handler));
7952 _TX_DLLIMPORT_OPT (
"Kernel32",
unsigned, RemoveVectoredExceptionHandler,(
void* handler));
7953 _TX_DLLIMPORT_OPT (
"Kernel32",
bool, GetModuleHandleEx, (DWORD
flags,
const char moduleName[], HMODULE* module));
7954 _TX_DLLIMPORT_OPT (
"Kernel32",
bool, IsWow64Process, (HANDLE process,
int* isWow64Process));
7955 _TX_DLLIMPORT_OPT (
"Kernel32",
bool, Wow64GetThreadContext, (HANDLE thread, WOW64_CONTEXT* context));
7956 _TX_DLLIMPORT_OPT (
"Kernel32",
bool, SetThreadStackGuarantee, (
unsigned long* stackSize));
7958 _TX_DLLIMPORT (
"OLE32", HRESULT, CoInitialize, (
void*));
7959 _TX_DLLIMPORT (
"OLE32", HRESULT, CoCreateInstance, (REFCLSID clsId, IUnknown*, DWORD, REFIID iId,
void** value));
7960 _TX_DLLIMPORT (
"OLE32",
void, CoUninitialize, (
void));
7962 _TX_DLLIMPORT (
"Shell32", HINSTANCE,ShellExecuteA, (HWND wnd,
const char operation[],
const char file[],
7963 const char parameters[],
const char directory[],
int showCmd));
7965 _TX_DLLIMPORT (
"ShlWAPI",
char*, StrStrIA, (
const char string[],
const char search[]));
7966 _TX_DLLIMPORT (
"ShlWAPI",
char*, StrStrIW, (
const wchar_t string[],
const wchar_t search[]));
7968 _TX_DLLIMPORT_OPT (
"NTDLL",
char*, wine_get_version, (
void));
7969 _TX_DLLIMPORT (
"NTDLL", NTSTATUS, NtQueryInformationProcess, (HANDLE process,
int infoClass,
7970 void* processInfo,
unsigned long szProcessInfo,
unsigned long* szReturnInfo));
7972 _TX_DLLIMPORT_CRT (
"MSVCRT",
void, exit, (
int retcode));
7973 _TX_DLLIMPORT_CRT (
"MSVCRT",
void, _cexit, (
void));
7974 _TX_DLLIMPORT_CRT (
"MSVCRT",
unsigned, _fpreset, (
void));
7975 _TX_DLLIMPORT_CRT (
"MSVCRT",
unsigned, _controlfp, (
unsigned control,
unsigned mask));
7976 _TX_DLLIMPORT_CRT (
"MSVCRT", uintptr_t,_beginthread, (
void (__cdecl* start_address) (
void*),
unsigned stack_size,
void* arglist));
7977 _TX_DLLIMPORT_CRT (
"MSVCRT", uintptr_t,_beginthreadex, (
void* security,
unsigned stack_size,
unsigned (__stdcall* start_address) (
void*),
7978 void *arglist,
unsigned init_flag,
unsigned* thread_addr));
7979 _TX_DLLIMPORT_CRT (
"MSVCRT",
char*, __unDName, (
char* outStr,
const char* mangledName,
int outStrLen,
7980 void* (*mallocFunc) (
size_t size),
void (*freeFunc) (
void *pointer),
7981 unsigned short flags));
7982 _TX_DLLIMPORT_CRT (
"MSVCRT", unexpected_handler, set_unexpected, (unexpected_handler handler));
7984 _TX_DLLIMPORT_OPT (
"OpenGL32", HDC, wglGetCurrentDC, (
void));
7985 _TX_DLLIMPORT_OPT (
"OpenGL32",
unsigned, glGetError, (
void));
7986 _TX_DLLIMPORT_OPT (
"Glu32",
const char*, gluErrorString, (
unsigned error));
7988 _TX_DLLIMPORT_OPT (
"ComDlg32", DWORD, CommDlgExtendedError, (
void));
7990 _TX_DLLIMPORT_OPT (
"DbgHelp*",
bool, MiniDumpWriteDump, (HANDLE process, DWORD processId, HANDLE file, MINIDUMP_TYPE dumpType,
7991 MINIDUMP_EXCEPTION_INFORMATION* exceptionParam,
7992 MINIDUMP_USER_STREAM_INFORMATION* userStreamParam,
7993 MINIDUMP_CALLBACK_INFORMATION* callbackParam));
7995 _TX_DLLIMPORT_OPT (
"DbgHelp*", DWORD, SymSetOptions, (DWORD options));
7996 _TX_DLLIMPORT_OPT (
"DbgHelp*",
bool, SymInitialize, (HANDLE process,
const char userSearchPath[],
bool invadeProcess));
7997 _TX_DLLIMPORT_OPT (
"DbgHelp*",
bool, SymFromAddr, (HANDLE process, DWORD64 addr, DWORD64* offset, SYMBOL_INFO* symbol));
7998 _TX_DLLIMPORT_OPT (
"DbgHelp*",
bool, SymGetLineFromAddr64, (HANDLE process, DWORD64 addr, DWORD* offset, IMAGEHLP_LINE64* line));
7999 _TX_DLLIMPORT_OPT (
"DbgHelp*", DWORD64, SymGetModuleBase64, (HANDLE process, DWORD64 addr));
8000 _TX_DLLIMPORT_OPT (
"DbgHelp*",
bool, SymCleanup, (HANDLE process));
8001 _TX_DLLIMPORT_OPT (
"DbgHelp*",
void*, SymFunctionTableAccess64, (HANDLE process, DWORD64 addrBase));
8002 _TX_DLLIMPORT_OPT (
"DbgHelp*",
bool, StackWalk64, (DWORD arch, HANDLE process, HANDLE thread, STACKFRAME64* frame,
void* ctxRecord,
8003 PREAD_PROCESS_MEMORY_ROUTINE64 readMemoryFunc,
8004 PFUNCTION_TABLE_ACCESS_ROUTINE64 tableAccessFunc,
8005 PGET_MODULE_BASE_ROUTINE64 getModuleBaseFunc,
8006 PTRANSLATE_ADDRESS_ROUTINE64 translateAddressFunc));
8008 _TX_DLLIMPORT_OPT (
"MgwHelp*", DWORD, SymSetOptions, (DWORD options));
8009 _TX_DLLIMPORT_OPT (
"MgwHelp*",
bool, SymInitialize, (HANDLE process,
const char userSearchPath[],
bool invadeProcess));
8010 _TX_DLLIMPORT_OPT (
"MgwHelp*",
bool, SymFromAddr, (HANDLE process, DWORD64 addr, DWORD64* offset, SYMBOL_INFO* symbol));
8011 _TX_DLLIMPORT_OPT (
"MgwHelp*",
bool, SymGetLineFromAddr64, (HANDLE process, DWORD64 addr, DWORD* offset, IMAGEHLP_LINE64* line));
8012 _TX_DLLIMPORT_OPT (
"MgwHelp*", DWORD64, SymGetModuleBase64, (HANDLE process, DWORD64 addr));
8013 _TX_DLLIMPORT_OPT (
"MgwHelp*",
bool, SymCleanup, (HANDLE process));
8014 _TX_DLLIMPORT_OPT (
"MgwHelp*",
void*, SymFunctionTableAccess64, (HANDLE process, DWORD64 addrBase));
8015 _TX_DLLIMPORT_OPT (
"MgwHelp*",
bool, StackWalk64, (DWORD arch, HANDLE process, HANDLE thread, STACKFRAME64* frame,
void* ctxRecord,
8016 PREAD_PROCESS_MEMORY_ROUTINE64 readMemoryFunc,
8017 PFUNCTION_TABLE_ACCESS_ROUTINE64 tableAccessFunc,
8018 PGET_MODULE_BASE_ROUTINE64 getModuleBaseFunc,
8019 PTRANSLATE_ADDRESS_ROUTINE64 translateAddressFunc));
8040 int _txInitialize();
8043 HWND _txCanvas_CreateWindow (
const SIZE* size);
8045 bool _txCanvas_OnCREATE (HWND wnd);
8046 bool _txCanvas_OnDESTROY (HWND wnd);
8047 bool _txCanvas_OnCLOSE (HWND);
8048 bool _txCanvas_OnPAINT (HWND wnd);
8049 bool _txCanvas_OnKEY (HWND wnd, WPARAM vk, LPARAM info,
bool down);
8050 bool _txCanvas_OnCHAR (HWND wnd, WPARAM ch, LPARAM info);
8051 bool _txCanvas_OnTIMER (HWND wnd, WPARAM
id);
8052 bool _txCanvas_OnMOUSEMOVE (HWND wnd, WPARAM buttons, LPARAM coords);
8053 bool _txCanvas_OnMOUSELEAVE (HWND wnd);
8054 bool _txCanvas_OnCREATEWND (HWND wnd, WPARAM, LPARAM lpar);
8055 bool _txCanvas_OnDESTROYWND (HWND wnd, WPARAM, LPARAM lpar);
8056 bool _txCanvas_OnCmdCONSOLE (HWND wnd, WPARAM cmd);
8057 bool _txCanvas_OnCmdABOUT (HWND wnd, WPARAM cmd);
8059 unsigned WINAPI _txCanvas_ThreadProc (
void* data);
8060 LRESULT CALLBACK _txCanvas_WndProc (HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar);
8062 HDC _txBuffer_Create (HWND wnd = NULL,
const POINT* size = NULL, HBITMAP bitmap = NULL,
8063 RGBQUAD** pixels = NULL) tx_nodiscard;
8064 bool _txBuffer_Delete (HDC* dc);
8065 bool _txBuffer_Select (HGDIOBJ obj, HDC dc =
txDC());
8067 HWND _txConsole_Attach();
8068 bool _txConsole_OK() tx_nodiscard;
8069 bool _txConsole_Detach (
bool activate);
8070 bool _txConsole_Draw (HDC dc);
8071 bool _txConsole_SetUnicodeFont();
8073 const
char* txRegisterClass (const
char classId[], WNDPROC wndProc,
unsigned style,
int backBrush,
int wndExtra);
8074 HWND txCreateExtraWindow (CREATESTRUCT createData);
8075 HICON _txCreateTXIcon (
int size) tx_nodiscard;
8076 int _txSetWindowText (HWND wnd, const
char* textRus, const
char* textEng = NULL,
8077 int checkOfs = 0, const
wchar_t checkLetters[2] = NULL);
8078 int _txPauseBeforeTermination (HWND canvas);
8079 int _txIsParentWaitable (DWORD* parentPID = NULL) tx_nodiscard;
8080 void _txActivateWindow (HWND wnd,
unsigned mode);
8083 LRESULT CALLBACK _txPlayVideo_WndProc (HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar);
8084 const
char* _txPlayVideo_FindVLC() tx_nodiscard;
8086 bool _txCreateShortcut (const
char shortcutName[],
8087 const
char fileToLink[], const
char args[] = NULL, const
char workDir[] = NULL,
8088 const
char description[] = NULL,
int cmdShow = SW_SHOWNORMAL,
8089 const
char iconFile[] = NULL,
int iconIndex = 0,
int fontSize = 0,
8090 COORD bufSize =
ZERO (COORD), COORD wndSize =
ZERO (COORD), COORD wndOrg =
ZERO (COORD));
8092 void* _tx_DLGTEMPLATE_Create (
void* globalMem,
size_t bufsize, DWORD style, DWORD exStyle,
8093 WORD controls,
short x,
short y,
short cx,
short cy,
8094 const
char caption[], const
char font[], WORD fontsize,
8095 const
char menu[]) tx_nodiscard;
8097 void* _tx_DLGTEMPLATE_Add (
void* dlgTemplatePtr,
size_t bufsize, DWORD style, DWORD exStyle,
8098 short x,
short y,
short cx,
short cy,
8099 WORD
id, const
char wclass[], const
char caption[]);
8101 const
char* _txProcessError (const
char file[],
int line, const
char func[],
unsigned color,
8102 const
char msg[], va_list args);
8103 void _txOnTerminate();
8104 void _txOnUnexpected();
8105 void _txOnPureCall();
8106 void _txOnNewHandlerAnsi();
8107 int _txOnNewHandler (
size_t size);
8108 void _txOnSignal (
int signal = 0,
int fpe = 0);
8109 BOOL WINAPI _txOnConsoleCtrlEvent (DWORD type);
8110 void _txOnSecurityError (
int code,
void*);
8111 void _txOnSecurityErrorAnsi (const
char* msg,
void* ptr,
int code);
8112 int _txOnMatherr (_exception* except);
8113 void _txOnInvalidParam (const
wchar_t* expr, const
wchar_t* func, const
wchar_t* file,
8114 unsigned line, uintptr_t);
8115 int _txOnAllocHook (
int type,
void* data,
size_t size,
int use,
long request,
8116 const
unsigned char* file,
int line);
8117 int _txOnRTCFailure (
int type, const
char* file,
int line, const
char* module, const
char* format, ...) tx_printfy (5);
8118 int _txOnErrorReport (
int type, const
char* text,
int* ret);
8119 int tx_glGetError (
int setError = INT_MIN);
8122 void _txOnExit (
int retcode);
8123 void _txOnFatalExit (
int retcode);
8124 void _txOnExitProcess (
unsigned retcode);
8125 void _txOnFatalAppExitA (
unsigned action, const
char message[]);
8126 bool _txOnTerminateProcess (HANDLE process,
unsigned retcode);
8127 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI
8128 _txOnSetUnhandledExceptionFilter (LPTOP_LEVEL_EXCEPTION_FILTER filter);
8129 void _txWatchdogTerminator (
void* timeout);
8131 long WINAPI _txVectoredExceptionHandler (EXCEPTION_POINTERS* exc);
8132 long WINAPI _txUnhandledExceptionFilter (EXCEPTION_POINTERS* exc);
8133 long _txOnExceptionSEH (EXCEPTION_POINTERS* exc, const
char func[]);
8134 intptr_t _txDumpExceptionSEH (
char what[], intptr_t size, const EXCEPTION_RECORD* exc, const
char func[]);
8135 intptr_t _txDumpExceptionObj (
char what[], intptr_t size,
void*
object,
size_t sizeObj, const std::type_info* type);
8136 intptr_t _txDumpExceptionCPP (
char what[], intptr_t size,
unsigned code = 0,
8137 unsigned params = 0, const ULONG_PTR info[] = NULL);
8139 void _txStackBackTrace (const
char file[] = "?",
int line = 0, const
char func[] = "?",
8140 bool readSource = true);
8141 const
char* _txCaptureStackBackTrace (
int framesToSkip = 0,
bool readSource = true,
8142 CONTEXT* context = NULL, EXCEPTION_POINTERS* exc = NULL, HANDLE thread = GetCurrentThread());
8143 int _txStackWalk (
int framesToSkip,
size_t szCapture,
void* capture[], CONTEXT* context = NULL,
8144 HANDLE thread = GetCurrentThread());
8145 const
char* _txCaptureStackBackTraceTX (
int framesToSkip = 0,
bool readSource = false);
8147 const
char* _txSymPrintFromAddr (
void* addr = NULL, const
char format[] = NULL, ...) tx_printfy (2);
8148 bool _txSymGetFromAddr (
void* addr, Win32::SYMBOL_INFO** symbol = NULL,
8149 Win32::IMAGEHLP_LINE64** line = NULL, const
char** module = NULL,
8150 const
char** source = NULL,
int context = 2);
8151 intptr_t _txReadSource (
char buf[], intptr_t size, const
char file[],
8152 int linStart = 0,
int linEnd = INT_MIN,
int linMark = INT_MIN);
8153 bool _txCreateMiniDump (EXCEPTION_POINTERS* exc = NULL);
8155 uintptr_t _txSetProcAddress (const
char funcName[], uintptr_t newFunc, const
char dllName[] = NULL,
8156 int useHotPatching = false, HMODULE module = NULL,
bool debug = false);
8157 bool _txInDll() tx_nodiscard;
8158 PROCESSENTRY32* _txFindProcess (
unsigned pid = GetCurrentProcessId()) tx_nodiscard;
8159 bool _txKillProcess (DWORD pid);
8160 int _txTaskKill (const
char name[] , const
char cmdLineSubstr[] ,
unsigned pid );
8161 bool _txCheckSourceCP (
int needCP =
_TX_CODEPAGE,
bool verbose = true);
8162 bool _txGetCommandLine (
wchar_t cmdLine[],
size_t szCmdLine,
unsigned pid = _getpid());
8163 IMAGE_NT_HEADERS*_txGetNtHeaders (HMODULE module = GetModuleHandle (NULL)) tx_nodiscard;
8164 bool _txIsConsoleSubsystem();
8165 const
char* _txAppInfo() tx_nodiscard;
8167 #if defined (_CLANG_VER) && !defined (_MSC_VER)
8168 void _txLibCppDebugFunction (std::__libcpp_debug_info
const& info);
8173 inline bool _txCanvas_OK () tx_nodiscard;
8174 int _txCanvas_SetRefreshLock (
int count);
8176 const
char* _txError (const
char file[] = NULL,
int line = 0, const
char func[] = NULL,
unsigned color = 0,
8177 const
char msg[] = NULL, ...) tx_printfy (5);
8179 bool _txIsBadReadPtr (const
void* address);
8181 intptr_t _tx_snprintf_s (
char stream[], intptr_t size, const
char format[], ...) tx_printfy (3);
8182 intptr_t _tx_vsnprintf_s (
char stream[], intptr_t size, const
char format[], va_list arg);
8183 bool _txIsTTY (
int fd);
8184 void txReopenStdio();
8186 #if defined (__CYGWIN__)
8189 int _putch (
int ch);
8190 int _kbhit() tx_nodiscard;
8197 #if !defined (NDEBUG)
8199 #define _TX_ARGUMENT_FAILED( cond ) ( !(cond) && \
8200 (SetLastErrorEx (ERROR_BAD_ARGUMENTS, 0), 1) && \
8201 (assert (cond), true) )
8203 #define _TX_TXWINDOW_FAILED() ( !txOK() && \
8204 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) && \
8205 (TX_ERROR ("\a" "Возможно, окно рисования не создано или не в порядке."), 1) )
8207 #define _TX_HDC_FAILED( dc ) ( !Win32::GetObjectType (dc) && \
8208 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) && \
8209 (TX_ERROR ("\a" "Параметр \"%s\" неверен." \
8210 " Возможно, этот холст не создан, или уже уничтожен, " \
8211 "или не загрузилась картинка.", #dc), 1) )
8212 #define _TX_DEFAULT_HDC_FAILED( dc ) ( !(dc) && \
8213 (TX_ERROR ("\a" "%s" \
8214 "Если вы указали параметр \"%s\", то он неверен.%s", \
8215 (!txWindow()? "Окно рисования не создано или не в порядке.\n" : ""), \
8217 ( txWindow()? " Возможно, этот холст не создан, или уже уничтожен, " \
8218 "или не загрузилась картинка." : "")), 1) )
8221 #define _TX_ARGUMENT_FAILED( cond ) ( !(cond) && \
8222 (SetLastErrorEx (ERROR_BAD_ARGUMENTS, 0), 1) )
8224 #define _TX_TXWINDOW_FAILED() ( !txOK() && \
8225 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) )
8227 #define _TX_HDC_FAILED( dc ) ( !Win32::GetObjectType (dc) && \
8228 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) )
8230 #define _TX_DEFAULT_HDC_FAILED( dc ) ( !(dc) && \
8231 (SetLastErrorEx (ERROR_INVALID_DATA, 0), 1) )
8238 #if !defined (NDEBUG)
8239 #define _TX_ON_DEBUG( code ) { code; }
8241 #define _TX_ON_DEBUG( code ) ;
8247 #define _TX_UNEXPECTED( ... ) $$ _txError (NULL, 0, NULL, 0, ##__VA_ARGS__)
8252 #define _TX_CALL( func, param ) ( (func)? ((func) param) : 0 )
8253 #define _TX_CALLv( func, param ) ( (func)? ((func) param) : (void)0 )
8258 #define _txWaitFor( cond, time ) { for (DWORD _t = GetTickCount() + (time); \
8259 !(cond) && GetTickCount() < _t; \
8260 Sleep (_txWindowUpdateInterval)) \
8264 _txTrace (__FILE__, __LINE__, NULL, "WARNING: Timeout: " #cond "."); }
8269 #define _txSetJmp() ( setjmp (_txDumpExceptionObjJmp) == 0 )
8271 #define _txClearJmp() { *(unsigned long long*) _txDumpExceptionObjJmp = 0; }
8303 const int _TX_IDM_ABOUT = 40000,
8304 _TX_IDM_CONSOLE = 40001,
8305 _TX_WM_CREATEWND = 0x7FF0,
8306 _TX_WM_DESTROYWND = 0x7FF1;
8310 volatile unsigned _txCanaryFirst = 0x776F656D;
8312 int _txInitialized = (
_TX_NOINIT +0)? 0 : _txInitialize();
8314 volatile unsigned _txMainThreadId = 0;
8315 volatile HANDLE _txMainThread = NULL;
8317 volatile unsigned _txCanvas_ThreadId = 0;
8318 volatile HANDLE _txCanvas_Thread = NULL;
8319 volatile HWND _txCanvas_Window = NULL;
8321 HDC _txCanvas_BackBuf[2] = {NULL,
8324 RGBQUAD* _txCanvas_Pixels = NULL;
8326 HBITMAP _txStockBitmap = NULL;
8329 CRITICAL_SECTION _txCanvas_LockBackBuf = {0,-1};
8331 UINT_PTR _txCanvas_RefreshTimer = 1;
8332 volatile int _txCanvas_RefreshLock = 0;
8334 ::std::vector<HDC>* _txCanvas_UserDCs = NULL;
8336 volatile bool _txConsole_IsBlinking =
true;
8338 int _txConsole =
false;
8339 bool _txMain =
false;
8340 bool _txIsDll =
false;
8341 volatile bool _txRunning =
false;
8342 volatile bool _txExit =
false;
8344 volatile POINT _txMousePos = {-1,-1};
8345 volatile unsigned _txMouseButtons = 0;
8347 volatile WNDPROC _txAltWndProc = NULL;
8349 _tx_thread _txLoc _txLoc::Cur = {};
8351 volatile int _txErrors = 0;
8352 volatile int _txOGLError = 0;
8353 volatile long _txSENumber = 0;
8354 volatile long _txSEFatalNumber = 0;
8358 LPTOP_LEVEL_EXCEPTION_FILTER _txPrevUEFilter = NULL;
8360 jmp_buf _txDumpExceptionObjJmp = {};
8362 const volatile uintptr_t _txForceImport[] = { (uintptr_t) ::TerminateProcess, (uintptr_t) ::ExitProcess,
8363 (uintptr_t) ::FatalExit, (uintptr_t) ::FatalAppExitA,
8364 (uintptr_t) ::exit, (uintptr_t) Win32::_controlfp,
8365 (uintptr_t) Win32::Polyline, (uintptr_t) Win32::PolyBezier,
8366 (uintptr_t) Win32::RoundRect, (uintptr_t) Win32::RemoveVectoredExceptionHandler,
8367 (uintptr_t) Win32::PlgBlt, (uintptr_t) Win32::RtlCaptureStackBackTrace,
8368 (uintptr_t) Win32::SymInitialize, (uintptr_t) Win32::MinGW::SymInitialize,
8369 (uintptr_t) Win32::SymSetOptions, (uintptr_t) Win32::MinGW::SymSetOptions,
8370 (uintptr_t) Win32::SymGetLineFromAddr64, (uintptr_t) Win32::MinGW::SymGetLineFromAddr64,
8371 (uintptr_t) Win32::SymFromAddr, (uintptr_t) Win32::MinGW::SymFromAddr,
8372 (uintptr_t) Win32::SymCleanup, (uintptr_t) Win32::MinGW::SymCleanup,
8373 (uintptr_t) Win32::SymGetModuleBase64, (uintptr_t) Win32::MinGW::SymGetModuleBase64,
8374 (uintptr_t) Win32::SymFunctionTableAccess64, (uintptr_t) Win32::MinGW::SymFunctionTableAccess64,
8375 (uintptr_t) Win32::StackWalk64, (uintptr_t) Win32::MinGW::StackWalk64,
8376 (uintptr_t) Win32::StrStrIA, (uintptr_t) Win32::Wow64GetThreadContext };
8378 volatile unsigned _txCanaryLast = 0x5E2E2E5E;
8384 extern volatile unsigned _txCanaryFirst;
8385 extern volatile unsigned _txCanaryLast;
8386 extern volatile HWND _txCanvas_Window;
8387 extern volatile unsigned _txCanvas_ThreadId;
8388 extern HDC _txCanvas_BackBuf[2];
8389 extern RGBQUAD* _txCanvas_Pixels;
8390 extern volatile int _txCanvas_RefreshLock;
8391 extern volatile WNDPROC _txAltWndProc;
8392 extern volatile bool _txExit;
8393 extern volatile int _txOGLError;
8413 if (_txInitialized)
return 1;
8416 #if defined (_TX_ALLOC_BREAK) && defined (_MSC_VER)
8417 _CrtSetBreakAlloc (_TX_ALLOC_BREAK);
8420 #if defined (_TX_ALLOW_TRACE)
8424 _TX_ON_DEBUG (OutputDebugString (
"\n");
8425 OutputDebugString (_TX_VERSION
" - The Dumb Artist Library, " _TX_AUTHOR
": \"" __FILE__
"\" "
8427 OutputDebugString (
"\n"));
8429 _txMainThreadId = GetCurrentThreadId();
8430 _txMainThread = OpenThread (THREAD_ALL_ACCESS,
false, _txMainThreadId);
8432 $3 _txIsDll = _txInDll();
8436 $ _txConsole = ! FindAtom (
"_txConsole");
8437 $ (void) AddAtom (
"_txConsole");
8445 $ _TX_CALL (Win32::SetThreadStackGuarantee, (&stackSize));
8454 $ _TX_CALL (Win32::AddVectoredExceptionHandler, (1, (PVECTORED_EXCEPTION_HANDLER) _txVectoredExceptionHandler));
8455 $ _txPrevUEFilter = SetUnhandledExceptionFilter ( (LPTOP_LEVEL_EXCEPTION_FILTER) _txUnhandledExceptionFilter);
8458 $ ::std::set_terminate (_txOnTerminate);
8459 $ ::std::set_new_handler (_txOnNewHandlerAnsi);
8460 $ _TX_CALL (Win32::set_unexpected, (_txOnUnexpected));
8462 #if defined (_CLANG_VER) && !defined (_MSC_VER)
8463 $ ::std::__libcpp_debug_function = _txLibCppDebugFunction;
8466 $ SetConsoleCtrlHandler (_txOnConsoleCtrlEvent,
true);
8468 $ SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
8470 #if defined (_MSC_VER)
8472 $ _set_printf_count_output (1);
8474 $ _set_new_handler (_txOnNewHandler);
8475 $ _set_new_mode (1);
8477 #if !defined (_CLANG_VER)
8479 $ _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF);
8480 $ _CrtSetAllocHook (_txOnAllocHook);
8482 $
unsigned mode = _CRTDBG_MODE_FILE;
8483 $
if (_CrtSetReportHook2 (_CRT_RPTHOOK_INSTALL, (_CRT_REPORT_HOOK) _txOnErrorReport) > 0) mode = 0;
8485 $ _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_DEBUG | mode);
8486 $ _CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_DEBUG | mode | _CRTDBG_MODE_WNDW);
8487 $ _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_DEBUG | mode | _CRTDBG_MODE_WNDW);
8488 $ _CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR);
8489 $ _CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDERR);
8490 $ _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR);
8494 $ _set_abort_behavior (_WRITE_ABORT_MSG, _WRITE_ABORT_MSG);
8495 $ _set_abort_behavior (0, _CALL_REPORTFAULT);
8497 $ _RTC_SetErrorFunc (_txOnRTCFailure);
8498 $ _set_purecall_handler (_txOnPureCall);
8499 $ _set_invalid_parameter_handler (_txOnInvalidParam);
8503 #if defined (__STDC_LIB_EXT1__)
8504 $ ::std::set_constraint_handler_s (_txOnSecurityErrorAnsi);
8507 #if !defined (__CYGWIN__) && defined (_GCC_VER) && (_GCC_VER >= 530) && !defined (i386)
8508 $ __setusermatherr (_txOnMatherr);
8511 #if !defined (__CYGWIN__)
8512 $ _set_error_mode (_OUT_TO_MSGBOX | _OUT_TO_STDERR);
8515 $ HWND console = _txConsole_Attach();
8519 $ _txSetProcAddress (
"ExitProcess", (uintptr_t) _txOnExitProcess,
"KERNEL32.DLL");
8520 $ _txSetProcAddress (
"TerminateProcess", (uintptr_t) _txOnTerminateProcess,
"KERNEL32.DLL");
8521 $ _txSetProcAddress (
"FatalExit", (uintptr_t) _txOnFatalExit,
"KERNEL32.DLL");
8522 $ _txSetProcAddress (
"FatalAppExitA", (uintptr_t) _txOnFatalAppExitA,
"KERNEL32.DLL");
8523 $ _txSetProcAddress (
"UnhandledExceptionFilter", (uintptr_t) _txUnhandledExceptionFilter,
"KERNEL32.DLL",
true);
8524 $ _txSetProcAddress (
"SetUnhandledExceptionFilter", (uintptr_t) _txOnSetUnhandledExceptionFilter,
"KERNEL32.DLL");
8525 $ _txSetProcAddress (
"exit", (uintptr_t) _txOnExit);
8526 $ _txSetProcAddress (
"_cexit", (uintptr_t) _txOnCExit);
8528 $ InitializeCriticalSection (&_txCanvas_LockBackBuf);
8530 $ HDC dc = Win32::CreateCompatibleDC (NULL); dc
asserted;
8531 $ _txStockBitmap = (HBITMAP) Win32::SelectObject (dc, Win32::CreateCompatibleBitmap (dc, 1, 1)); _txStockBitmap
asserted;
8532 $ Win32::DeleteObject (Win32::SelectObject (dc, _txStockBitmap))
asserted;
8535 $ atexit (_txCleanup);
8543 $ srand ((
unsigned) time (NULL));
8548 #if !defined (__CYGWIN__)
8553 $ Win32::CoCreateInstance = Win32::CoCreateInstance;
8560 bool _txCheckSourceCP (
int needCP ,
bool verbose )
8562 $3
const char* sCodePage = NULL;
8565 $
switch (((
unsigned const char*)
"А ) [0])
{
case 192: {$ codePage = 1251; sCodePage = "1251."; break; }
case 208: {$ codePage = 65001; sCodePage = "UTF-8."; break; }
case 128: {$ codePage = 866; sCodePage = "866."; break; }
case 225: {$ codePage = 20866; sCodePage = "KOI-8, waaat?!"; break; }
default: {$ codePage = -1; sCodePage = "(Unknown)"; break; }
}
$ if (codePage != needCP && verbose)
{
$ *_txTraceSE = ' '; // No stack trace please
$ _TX_UNEXPECTED ("\v\t" "\n\n" "WARNING: CHECK TXLib.h file CODEPAGE. Maybe it is %s It should be %d.\n\n"
"This is NOT an error of TXLib itself. Please note:\n\n"
"Do NOT copy-and-paste TXLib.h file contents into a new file and them save it inside your "
"IDE or editor. This can change original TXLib codepage (%d) to another one. Instead, DO "
"use copy / move / cut-and-paste operations in Windows Explorer (Far Manager etc) only. "
"Or, when you see TXLib.h being opened in browser, use 'Save as...' (Ctrl+S) command.\n\n"
"Now you should re-download TXLib.h file from the http://txlib.ru site.\n\n"
"You can continue, but Russian messages and symbols may appear unreadable.",
sCodePage, needCP, needCP);
}
$ return (codePage == needCP);
}
//-----------------------------------------------------------------------------------------------------------------
void (*_txDllImport (const char dllFileName[], const char funcName[], bool required /*= true*/)) ()
{
if (_TX_ARGUMENT_FAILED (dllFileName && *dllFileName)) return NULL;
if (_TX_ARGUMENT_FAILED (funcName && *funcName)) return NULL;
static char dllPaths [2][MAX_PATH] = {"", ""};
if (!*dllPaths[0])
{
const char dllDir[] = "\\Windows\\";
// dllPaths[0] is relative to the TX Setup directory stored in the Registry
char* path = dllPaths[0];
txRegQuery ("HKCU\\Software\\TX Library", "ProductDir", path, MAX_PATH);
strncat_s (path, MAX_PATH, dllDir, sizeof (dllDir) - 1);
// dllPaths[1] is relative to TXib.h file used in compilation
path = dllPaths[1];
if (strchr (__FILE__, ':'))
{
strncpy_s (path, MAX_PATH, __FILE__, sizeof (__FILE__) - 1);
}
else
{
GetCurrentDirectory (MAX_PATH, path);
strncat_s (path, MAX_PATH, "\\" __FILE__, sizeof ("\\" __FILE__) - 1);
}
if (char* dir = strrchr (path, '\\')) *dir = 0;
strncat_s (path, MAX_PATH, dllDir, sizeof (dllDir) - 1);
}
char dllName[MAX_PATH] = "", dllArch[MAX_PATH] = "";
const char* arch = (dllFileName? strchr (dllFileName, '*') : NULL); //-V547
if (arch)
{
assert (arch >= dllFileName); //-V547
strncpy_s (dllName, sizeof (dllName), dllFileName, (size_t) (arch - dllFileName));
strncat_s (dllName, sizeof (dllName), arch+1, sizeof (dllName) - 1 - strlen (dllName));
strncpy_s (dllArch, sizeof (dllArch), dllFileName, (size_t) (arch - dllFileName));
strncat_s (dllArch, sizeof (dllArch), sizeof (void*) == 8? "64" : "32", 3);
strncat_s (dllArch, sizeof (dllArch), arch+1, sizeof (dllArch) - 1 - strlen (dllArch));
}
else if (dllFileName) //-V547 //-V2516
{
strncat_s (dllName, sizeof (dllName), dllFileName, sizeof (dllName) - 1);
}
HMODULE dll = GetModuleHandle (dllFileName);
if (!dll) dll = GetModuleHandle (dllArch);
if (!dll) dll = GetModuleHandle (dllName);
for (int i = 0; !dll && i < (int) sizearr (dllPaths); i++)
{
char path [MAX_PATH] = "";
strncpy_s (path, sizeof (path), dllPaths[i], sizeof (dllPaths[i]));
size_t len = strlen (path);
strncpy_s (path + len, sizeof (path) - len, dllArch, sizeof (dllArch));
if (!dll) dll = LoadLibrary (path); //-V547
strncpy_s (path + len, sizeof (path) - len, dllName, sizeof (dllName));
if (!dll) dll = LoadLibrary (path);
}
if (!dll) dll = LoadLibrary (dllArch);
if (!dll) dll = LoadLibrary (dllName);
if (!dll && required) TX_ERROR ("\a" "Cannot load library \"%s%s%s\".",
dllName, (arch? "\" / \"" : ""), dllArch);
if (!dll) return NULL;
void (*addr)() = (void(*)()) GetProcAddress (dll, funcName);
if (!addr && required) TX_ERROR ("\a" "Cannot import \"%s\" from library \"%s%s%s\".",
funcName, dllName, (arch? "\" / \"" : ""), dllArch);
return addr;
}
//-----------------------------------------------------------------------------------------------------------------
#if defined (_MSC_VER) && (_MSC_VER == 1800) // MSVC 2013
#pragma warning (push)
#pragma warning (disable: 6102) // Использование 'name' из завершившегося ошибкой вызова функции
#endif
int txRegQuery (const char* keyName, const char* valueName, void* value, size_t szValue)
{
if (_TX_ARGUMENT_FAILED (keyName)) return 0;
HKEY hive = NULL;
#define EQU_(name1, name2) ( _strnicmp (keyName, name1 "\\", sizeof (name1)) == 0 || \
_strnicmp (keyName, name2 "\\", sizeof (name2)) == 0 )
if (EQU_("HKLM", "HKEY_LOCAL_MACHINE")) hive = HKEY_LOCAL_MACHINE;
else if (EQU_("HKCU", "HKEY_CURRENT_USER")) hive = HKEY_CURRENT_USER;
else if (EQU_("HKCR", "HKEY_CLASSES_ROOT")) hive = HKEY_CLASSES_ROOT;
else if (EQU_("HKU", "HKEY_USERS")) hive = HKEY_USERS;
else if (EQU_("HKCC", "HKEY_CURRENT_CONFIG")) hive = HKEY_CURRENT_CONFIG;
else { _TX_ARGUMENT_FAILED (("keyName должно начинаться с HKLM\\, HKCU\\, HKCR\\, HKU\\ или HKCC\\ ", hive)); return 0; }
#undef EQU_
keyName = strchr (keyName, '\\') + 1; //-V769
assert (keyName > (const char*) 1);
HKEY key = NULL;
DWORD size = 0;
bool ok = (RegOpenKeyEx (hive, keyName, 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS);
if (ok) ok &= (RegQueryValueEx (key, valueName, NULL, NULL, NULL, &size) == ERROR_SUCCESS);
if (ok && value && size < szValue) ok &= (RegQueryValueEx (key, valueName, NULL, NULL, (BYTE*) value, &size) == ERROR_SUCCESS); //-V104
if (key) ok &= (RegCloseKey (key) == ERROR_SUCCESS);
return size;
}
#if defined (_MSC_VER) && (_MSC_VER == 1800)
#pragma warning (pop)
#endif
#endif // TX_COMPILED
//}
//-----------------------------------------------------------------------------------------------------------------
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
HWND txCreateWindow (double sizeX, double sizeY, bool centered /*= true*/)
{
$1 if (!_txInitialized) _txInitialized = _txInitialize();
$ if (HWND wnd = txWindow())
{
$ SetLastErrorEx (ERROR_INVALID_DATA, 0);
$ _TX_ON_DEBUG (TX_ERROR ("\a" "Окно рисования уже создано!"));
$ return wnd;
}
$ if (!_txIsDll)
{
$ _txMain = ! FindAtom ("_txMain"); // Not a thread-safe
$ (void) AddAtom ("_txMain"); //-V530
}
$ if (_txWindowUpdateInterval < 10) {$ _txWindowUpdateInterval = 10; } //-V1048
$ _txRunning = false;
// Store the size
$ static SIZE size = { ROUND (sizeX), ROUND (sizeY) };
$ if (centered) { size.cx *= -1; size.cy *= -1; }
// In Thread, where REAL creation lies...
$ unsigned id = 0;
$ _txCanvas_Thread = (HANDLE) Win32::_beginthreadex (NULL, 0, _txCanvas_ThreadProc, &size, 0, &id);
$ if (!_txCanvas_Thread) return TX_DEBUG_ERROR ("\a" "Cannot start canvas thread."), (HWND) NULL;
$ _txWaitFor (_txRunning, 10*_TX_TIMEOUT);
$ if (!_txRunning) return TX_DEBUG_ERROR ("\a" "Cannot create canvas window."), (HWND) NULL;
$ if (!txOK()) return TX_DEBUG_ERROR ("\a" "Canvas window is not OK."), (HWND) NULL;
$ HWND console = Win32::GetConsoleWindow();
$ DWORD proc = 0;
$ GetWindowThreadProcessId (console, &proc);
$ if (console && (proc == GetCurrentProcessId() || _txIsParentWaitable()))
{$ ShowWindow (console, TX_CONSOLE_MODE); }
$ HMENU menu = GetSystemMenu (txWindow(), false);
if (menu) {$ CheckMenuItem (menu, _TX_IDM_CONSOLE, (console? (IsWindowVisible (console)? MF_CHECKED : 0) : MF_DISABLED)); }
$ Win32::GdiSetBatchLimit (1);
$ SetLastError (0);
$ errno = 0;
#if !defined (__CYGWIN__)
$ _doserrno = 0;
#endif
$ return txWindow();
}
//-----------------------------------------------------------------------------------------------------------------
HWND txCreateExtraWindow (CREATESTRUCT createData)
{
$1 if (_TX_TXWINDOW_FAILED()) return NULL;
$ volatile HWND wnd = NULL;
$ createData.hInstance = (HINSTANCE)(uintptr_t) &wnd;
$ PostMessage (txWindow(), _TX_WM_CREATEWND, 0, (LPARAM) &createData) asserted;
$ _txWaitFor (wnd, 5*_TX_TIMEOUT);
$ return wnd;
}
//-----------------------------------------------------------------------------------------------------------------
bool txSetDefaults (HDC dc /*= txDC()*/)
{
$1 if (dc == txDC()) txUpdateWindow (false); //-V601
$ txAutoLock _lock;
$ RECT r = {};
$ GetClientRect (Win32::GetConsoleWindow(), &r);
$ SIZE szCon = { r.right - r.left, r.bottom - r.top };
$ HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
$ CONSOLE_SCREEN_BUFFER_INFO con = {{80, 25}, {}, 0, {0, 0, 80-1, 25-1}, {80, 25}};
$ GetConsoleScreenBufferInfo (out, &con);
$ SIZE szTxt = { (short) (con.srWindow.Right - con.srWindow.Left + 1),
(short) (con.srWindow.Bottom - con.srWindow.Top + 1) };
//{ Set defaults for graphics layer
$ _txBuffer_Select (Win32::GetStockObject (WHITE_PEN), dc) asserted;
$ _txBuffer_Select (Win32::GetStockObject (WHITE_BRUSH), dc) asserted;
$ _txBuffer_Select (Win32::CreateFont (szCon.cy/szTxt.cy, szCon.cx/szTxt.cx,
0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FIXED_PITCH, TX_CONSOLE_FONT),
dc) asserted;
$ (Win32::SetTextColor (dc, TX_WHITE) != CLR_INVALID) asserted;
$ Win32::SetBkMode (dc, TRANSPARENT) asserted;
$ Win32::SetROP2 (dc, R2_COPYPEN) asserted;
$ Win32::SetStretchBltMode (dc, HALFTONE) asserted;
//}
$ if (dc != txDC())
{$ return true; }
//{ Set defaults for console layer
$ POINT szCanvas = txGetExtent (dc);
$ HGDIOBJ font = txFontExist (TX_CONSOLE_FONT)?
Win32::CreateFont (szCanvas.y/szTxt.cy, szCanvas.x/szTxt.cx,
0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FIXED_PITCH, TX_CONSOLE_FONT)
:
Win32::GetStockObject (SYSTEM_FIXED_FONT);
$ _txBuffer_Select (font, _txCanvas_BackBuf[1]);
//}
//{ Scroll the console for text to go above top of window and don't mix with graphics
$ if (con.dwCursorPosition.X) _putch ('\n');
$ short delta = (short) (con.dwCursorPosition.Y - con.srWindow.Top);
$ con.srWindow.Top = (short) (con.srWindow.Top + delta);
$ con.srWindow.Bottom = (short) (con.srWindow.Bottom + delta);
$ SMALL_RECT src = { 0, 0, (short) (con.dwSize.X - 1), (short) (con.dwSize.Y - 1) };
$ CHAR_INFO fill = { {' '}, FOREGROUND_LIGHTGRAY };
$ COORD dest = { 0, (short) -delta }; // New UL-corner of src, scroll up
$ con.dwCursorPosition.X = 0;
$ con.dwCursorPosition.Y = (short) (con.dwCursorPosition.Y - delta);
$ (con.srWindow.Bottom < con.dwSize.Y && // Move the "window"
SetConsoleWindowInfo (out, true, &con.srWindow))
||
(ScrollConsoleScreenBuffer (out, &src, NULL, dest, &fill), // Or scroll the buffer
SetConsoleCursorPosition (out, con.dwCursorPosition));
//}
$ txUpdateWindow (true); //-V601
return true;
}
#endif // TX_COMPILED
//-----------------------------------------------------------------------------------------------------------------
inline bool txOK()
{
return (_txCanaryFirst == 0x776F656D && // Too well-known values to use constants. You know these values, don't you?
_txCanaryLast == 0x5E2E2E5E &&
_txCanvas_OK()
#if defined (_MSC_VER)
&& _CrtCheckMemory()
#endif
);
}
//-----------------------------------------------------------------------------------------------------------------
//{ Cleanup
//-----------------------------------------------------------------------------------------------------------------
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
// Implicit std(MSVCRT.dll)::_cexit() call before _txCleanup can lead to hangs in _cexit handlers chain.
// So redefining ::std::_cexit(). Do it dynamically via PE Import Table hook to avoid duplicate symbols
// if several modules linked together include TXLib.h. See _txSetProcAddress() call in _txInitialize().
void _txOnCExit()
{
OutputDebugString ("\n");
$5 _txCleanup();
_TX_CALLv (Win32::_cexit, ());
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnExit (int retcode)
{
if (retcode != 0)
{
OutputDebugString ("\n");
txOutputDebugPrintf ("%s - WARNING: %s:%d called\n", _TX_VERSION, __func__, retcode);
}
$5 _txCleanup();
if (retcode != 0)
txOutputDebugPrintf ("%s - WARNING: calling Win32::exit (%d)\n", _TX_VERSION, retcode);
Win32::exit (retcode);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnExitProcess (unsigned retcode)
{
if (retcode != 0)
{
OutputDebugString ("\n");
txOutputDebugPrintf ("%s - WARNING: %s (%u) called\n", _TX_VERSION, __func__, retcode);
}
$5 _txCleanup();
if (retcode != 0)
txOutputDebugPrintf ("%s - WARNING: calling Win32::ExitProcess (%u)\n", _TX_VERSION, retcode);
Win32::ExitProcess (retcode);
}
//-----------------------------------------------------------------------------------------------------------------
bool _txOnTerminateProcess (HANDLE process, unsigned retcode)
{
if (retcode != 0)
{
OutputDebugString ("\n");
txOutputDebugPrintf ("%s - WARNING: %s (0x%p, %u) called\n", _TX_VERSION, __func__, process, retcode);
}
$5 _txCleanup();
if (retcode != 0)
txOutputDebugPrintf ("%s - WARNING: calling Win32::TerminateProcess (0x%p, %u)\n", _TX_VERSION, process, retcode);
return Win32::TerminateProcess (process, retcode);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnFatalExit (int retcode)
{
OutputDebugString ("\n");
txOutputDebugPrintf ("%s - WARNING: %s:%d called\n", _TX_VERSION, __func__, retcode);
$5 _txCleanup();
txOutputDebugPrintf ("%s - WARNING: calling Win32::FatalExit (%d)\n", _TX_VERSION, retcode);
_TX_CALLv (Win32::FatalExit, (retcode));
txOutputDebugPrintf ("%s - WARNING: Win32::FatalExit() failure, calling Win32::TerminateProcess (%d)\n", _TX_VERSION, retcode);
Win32::TerminateProcess (GetCurrentProcess(), retcode);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnFatalAppExitA (unsigned action, const char message[])
{
OutputDebugString ("\n");
txOutputDebugPrintf ("%s - WARNING: %s (%u, \"%s\") called\n", _TX_VERSION, __func__, action, message);
$5 _txCleanup();
txOutputDebugPrintf ("%s - WARNING: calling Win32::FatalAppExitA (%u, %s)\n", _TX_VERSION, action, message);
_TX_CALLv (Win32::FatalAppExitA, (action, message));
txOutputDebugPrintf ("%s - WARNING: Win32::FatalExit() failure, calling Win32::TerminateProcess (EXIT_FAILURE)\n", _TX_VERSION);
Win32::TerminateProcess (GetCurrentProcess(), EXIT_FAILURE);
}
//-----------------------------------------------------------------------------------------------------------------
BOOL WINAPI _txOnConsoleCtrlEvent (DWORD type)
{
OutputDebugString ("\n");
txOutputDebugPrintf ("%s - WARNING: %s (0x%04lX) called\n", _TX_VERSION, __func__, (unsigned long) type);
$5 switch (type)
{
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT: $ _txExit = true;
$ _txCleanup();
case CTRL_C_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_BREAK_EVENT:
default: break; //-V2522
}
$ return false;
}
//-----------------------------------------------------------------------------------------------------------------
void _txCleanup()
{
if (!_txInitialized) return;
else _txInitialized = false; //-V601
$3 _txRunning = false;
$ _txConsole_IsBlinking = false;
$ txSetProgress (100, (!_txErrors)? Win32::TBPF_PAUSED : Win32::TBPF_ERROR);
$ txSetWindowsHook (NULL);
$ HWND canvas = txWindow();
$ HWND console = Win32::GetConsoleWindow();
$ unsigned thread = GetCurrentThreadId();
$ HWND wnd = (canvas)? canvas : console;
$ bool externTerm = (thread != _txMainThreadId &&
thread != _txCanvas_ThreadId);
$ DWORD parent = 0;
$ int isParentWaitable = _txIsParentWaitable (&parent);
$ bool waitableParent = !externTerm && isParentWaitable;
$ if (canvas)
{$ txSleep (5*_txWindowUpdateInterval); }
$ if (_txConsole)
{
$ if (_txMain) txSetConsoleAttr (FOREGROUND_LIGHTGRAY);
$ if (console)
{
$ EnableWindow (console, true);
$ _txSetWindowText (console, " [ЗАВЕРШЕНО]", " [FINISHED]", 2, L"\x0417" /* 'З' */ L"\x0046" /* 'F' */);
}
}
$ if (_txMain && !externTerm && canvas)
{$ _txSetWindowText (canvas, " [ЗАВЕРШЕНО]", " [FINISHED]", 2, L"\x0417" /* 'З' */ L"\x0046" /* 'F' */); }
$ std::cout.flush();
$ std::cerr.flush();
$ std::clog.flush();
$ _flushall();
$ bool paused = false;
$ if (((canvas? _txMain : _txConsole) && !_txExit) || (_txErrors && thread == _txMainThreadId))
{
$ if (wnd)
{
$ if (isParentWaitable >= 0)
{$ _txActivateWindow (wnd, 0x08); }
$ EnableWindow (wnd, true);
}
$ if (console && isParentWaitable >= 0)
{
$ txPause ((_txErrors)? "\f\n" "[Press F to Pay Respects...]" :
(!canvas && _txIsTTY (0))? "\f\n" "[Нажмите любую клавишу для завершения]" : "\f");
$ paused = true;
}
}
$ if (_txConsole && _txWatchdogTimeout >= 0)
{$ Win32::_beginthread (_txWatchdogTerminator, 0, &_txWatchdogTimeout); }
$ if (txWindow())
{$ SendNotifyMessage (txWindow(), WM_DESTROY, 0, 0); }
$ _txWaitFor (!txWindow(), 5*_TX_TIMEOUT);
$ txSpeak (NULL);
$ txPlayVideo (NULL);
$ delete _txCanvas_UserDCs;
$ _txCanvas_UserDCs = NULL;
$ if (GetCurrentThreadId() != _txMainThreadId)
{$ SuspendThread (_txMainThread); } //-V720
$ if (GetCurrentThreadId() != _txCanvas_ThreadId)
{$ SuspendThread (_txCanvas_Thread); } //-V720
$ if (_txMainThread)
{$ CloseHandle (_txMainThread) asserted; _txMainThread = NULL; }
$ if (_txCanvas_Thread)
{$ CloseHandle (_txCanvas_Thread) asserted; _txCanvas_Thread = NULL; }
$ if (!txWindow())
{$ DeleteCriticalSection (&_txCanvas_LockBackBuf); CRITICAL_SECTION zero = {0, -1}; _txCanvas_LockBackBuf = zero; }
$ bool parentKilled = false;
$ if (waitableParent && paused && _txNOP (_TX_ALLOW_KILL_PARENT))
{
$ console = Win32::GetConsoleWindow();
$ if (parent)
{$ parentKilled = _txKillProcess (parent); }
$ if (parent && !parentKilled)
{
$ PostMessage (console, WM_KEYDOWN, VK_RETURN, 0x001C0001); // Scancode = 0x1C, Count = 1
$ PostMessage (console, WM_KEYUP, VK_RETURN, 0xC01C0001); // Scancode = 0x1C, Count = 1, Prev = 1, Trans = 1
}
}
$ if (_txConsole)
{$ _txSetWindowText (console, NULL); }
$ if (_txMain && _txConsole)
{$ _txConsole_Detach (waitableParent && !parentKilled && !externTerm); } //-V560
$ std::cout.flush();
$ std::cerr.flush();
$ std::clog.flush();
$ _flushall();
$ _txSymGetFromAddr (NULL);
// That's all, folks
_TX_ON_DEBUG (OutputDebugString ("\n");
OutputDebugString (_TX_VERSION " - FINISHED: " _TX_MODULE "\n");
OutputDebugString ("\n"));
}
//-----------------------------------------------------------------------------------------------------------------
int txPause (const char* message /*= NULL*/, ...)
{
$3 bool wine = !!Win32::wine_get_version;
$ HWND canvas = txWindow();
$ HWND console = Win32::GetConsoleWindow();
$ HWND wnd = (canvas)? canvas : console;
$ bool istty0 = _txIsTTY (0);
$ int attr = txGetConsoleAttr();
$ int oldCP = GetConsoleOutputCP();
$ SetConsoleOutputCP (_TX_CODEPAGE);
if (!message) {$ message = "[Нажмите любую клавишу для продолжения]"; }
if (*message != '\f') {$ _txSetWindowText (wnd, " [Нажмите клавишу...]", " [Press a key...]"); }
else {$ message++; }
if (*message != '\v') {$ txSetConsoleAttr (FOREGROUND_LIGHTGRAY); }
else {$ message++; }
$ _txActivateWindow (wnd, 0x08);
$ va_list args;
$ va_start (args, message);
$ vfprintf (stderr, message, args);
$ txOutputDebugPrintf (message, args);
$ va_end (args);
$ fflush (stderr);
$ txSleep();
$ Win32::FLASHWINFO flash = { sizeof (flash), wnd, FLASHW_ALL | FLASHW_TIMERNOFG, 0xFFFFFFFF };
$ _TX_CALL (Win32::FlashWindowEx, (&flash));
$ int ch = EOF;
if (istty0) {$ while (!wine && _kbhit()) ch = _getch(); }
$ for (int i = 1; ; i++) //-V2530
{
$ Sleep (_txWindowUpdateInterval);
if (!istty0 && !canvas) {$ break; } // No need to run and hide
if (!wine && (ch = _txGetInput()) != EOF) {$ break; } // Somebody hit something.
if (canvas && !_txCanvas_ThreadId) {$ break; } // There was a window, and now there is not.
if (!Win32::GetConsoleWindow()) {$ break; } // Console was destroyed
if (_TX_CALL (Win32::GhostWindowFromHungWindow, (canvas)))
{$ TX_ERROR ("Похоже, программа зависла :("); break; }
if (canvas && _TX_CALL (Win32::IsHungAppWindow, (canvas)))
{$ _txTrace (__FILE__, __LINE__, NULL, "WARNING: Программа-таки зависла"); break; }
if (canvas && !SendMessageTimeout (canvas, WM_NULL, 0,0, SMTO_BLOCK | SMTO_ABORTIFHUNG, _TX_TIMEOUT, NULL))
{$ _txTrace (__FILE__, __LINE__, NULL, "WARNING: Программа не отвечает"); break; }
if (!wine && !(i % 100500))
{$ fprintf (stderr, "\r" "[Так нажмите же какую-нибудь клавишу...] \b\b"); }
}
if (istty0) {$ while (!wine && _kbhit()) ch = _getch(); }
$ _txSetWindowText (wnd, NULL);
$ fprintf (stderr, "\n");
if (ch == 3 /* Ctrl+C */) {$ raise (SIGABRT); }
$ SetConsoleOutputCP (oldCP);
$ txSetConsoleAttr (attr);
$ return ch;
}
//-----------------------------------------------------------------------------------------------------------------
int _txGetInput()
{
$4 HANDLE con = GetStdHandle (STD_INPUT_HANDLE);
$ int ch = EOF;
$ DWORD nChars = 0;
$ if (GetConsoleMode (con, &nChars) == 0 &&
PeekNamedPipe (con, NULL, 0, NULL, &nChars, NULL))
{
$ ch = (nChars)? fgetc (stdin) : EOF;
}
else if (_kbhit())
{
$ ch = _getch();
}
#if defined (_MSC_VER) && (_MSC_VER < 1700)
else if (fseek (stdin, 1, SEEK_CUR) != EOF)
{
$ (void) fseek (stdin, -1, SEEK_CUR);
$ ch = fgetc (stdin); // This causes blocking in MSVC 2011 beta
}
#endif
if (ch == 3 /* Ctrl+C */) {$ raise (SIGABRT); }
$ return ch;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txIsTTY (int fd)
{
$4 return GetFileType ((HANDLE)_get_osfhandle (fd)) == FILE_TYPE_CHAR;
}
//-----------------------------------------------------------------------------------------------------------------
int _txSetWindowText (HWND wnd, const char* textRus, const char* textEng /*= NULL*/,
int checkOfs /*= 0*/, const wchar_t checkLetters[2] /*= NULL*/)
{
struct tools
{
static LRESULT getWindowText (HWND window, wchar_t text[], size_t size)
{
$3 memset (text, 0, size * sizeof (*text));
$ return SendMessageTimeoutW (window, WM_GETTEXT, (WPARAM) size, (LPARAM) text, SMTO_BLOCK | SMTO_ABORTIFHUNG, _TX_TIMEOUT, NULL);
}
static LRESULT setWindowText (HWND window, wchar_t text[])
{
$1 return SendMessageTimeoutW (window, WM_SETTEXT, 0, (LPARAM) text, SMTO_BLOCK | SMTO_ABORTIFHUNG, _TX_TIMEOUT, NULL);
}
};
$1 static wchar_t _tx_thread title [_TX_BUFSIZE+15] = L"TXLib";
$ static wchar_t _tx_thread oldTitle [_TX_BUFSIZE+15] = L"TXLib";
$ if (!textRus)
{
$ tools::setWindowText (wnd, oldTitle);
$ return -1;
}
$ tools::getWindowText (wnd, title, _TX_BUFSIZE-1);
$ int len = (int) wcslen (title); if (len >= (int)_TX_BUFSIZE) len = _TX_BUFSIZE-1;
$ memcpy (oldTitle, title, sizeof (oldTitle));
$ if (textRus)
{
$ MultiByteToWideChar (_TX_CODEPAGE, 0, textRus, -1, title + len, (int)_TX_BUFSIZE - len);
$ tools::setWindowText (wnd, title);
$ tools::getWindowText (wnd, title, _TX_BUFSIZE-1);
if (checkLetters && len <= (int)_TX_BUFSIZE-1-2 && title [len + checkOfs] == checkLetters[0]) {$ return 0; }
if (!checkLetters) {$ return -2; }
}
$ if (textEng)
{
$ MultiByteToWideChar (_TX_CODEPAGE, 0, textEng, -1, title + len, (int)_TX_BUFSIZE - len);
$ tools::setWindowText (wnd, title);
$ tools::getWindowText (wnd, title, _TX_BUFSIZE-1);
if (checkLetters && len <= (int)_TX_BUFSIZE-1-2 && title [len + checkOfs] == checkLetters[1]) {$ return 1; }
if (!checkLetters) {$ return -2; }
}
$ return -3;
}
//-----------------------------------------------------------------------------------------------------------------
int _txIsParentWaitable (DWORD* parentPID /*= NULL*/)
{
$4 PROCESSENTRY32* info = _txFindProcess();
$ if (!info) return 0;
$ info = _txFindProcess (info->th32ParentProcessID);
$ if (!info) return 0;
$ char parent [MAX_PATH] = "";
$ strncpy_s (parent, sizeof (parent), info->szExeFile, sizeof (parent) - 1);
$ if (parentPID) *parentPID = info->th32ProcessID;
$ info = _txFindProcess (info->th32ParentProcessID); // info: grandparent
$ char list[_TX_BUFSIZE] = _TX_WAITABLE_PARENTS;
$ char* ctx = NULL;
$ for (char* p = strtok_s (list, ", ", &ctx); p; p = strtok_s (NULL, ", ", &ctx))
{
$ char* gp = strchr (p, ':');
$ if (gp)
{
$ *gp++ = 0;
$ if (_stricmp (p, parent) != 0) { continue; }
$ if (info) if (_stricmp (gp, info->szExeFile) == 0) // Was &&, but MSVC /analyze is so paranoid
{$ return islower ((unsigned char) *gp)? +1 : -1; }
}
else
{
$ if (_stricmp (p, parent) == 0)
{$ return islower ((unsigned char) *p)? +1 : -1; }
}
}
$ return 0;
}
//-----------------------------------------------------------------------------------------------------------------
void _txWatchdogTerminator (void* timeout) // Or Watchcat? Possibly will change in future versions
{
$3 if (_TX_ARGUMENT_FAILED (timeout)) return;
$ Sleep (*(int*) timeout); //-V206
$ OutputDebugString ("\n");
txOutputDebugPrintf ("%s - WARNING: %s(): Timeout (%d) expired, activating. %s\n", // Kinda static reflection...
_TX_VERSION, __func__, *(int*) timeout, ((__func__[8] == 'd')? "Bark, bark" : "Meow, meow")); //-V206
$ DWORD parent = 0;
$ if (_txIsParentWaitable (&parent))
{
txOutputDebugPrintf ("%s - WARNING: %s(): Calling _txKillProcess (0x%04lu)\n",
_TX_VERSION, __func__, (unsigned long) parent);
$ _txKillProcess (parent);
$ HWND console = GetConsoleWindow();
$ PostMessage (console, WM_KEYDOWN, VK_RETURN, 0x001C0001); // Scancode = 0x1C, Count = 1
$ PostMessage (console, WM_KEYUP, VK_RETURN, 0xC01C0001); // Scancode = 0x1C, Count = 1, Prev = 1, Trans = 1
}
txOutputDebugPrintf ("%s - WARNING: %s(): Calling Win32::TerminateProcess (EXIT_FAILURE)\n", _TX_VERSION, __func__);
$ Win32::TerminateProcess (GetCurrentProcess(), EXIT_FAILURE);
}
#endif // TX_COMPILED
//}
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//{ Tools
//-----------------------------------------------------------------------------------------------------------------
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
// You are here, little hacker?
int _txTaskKill (const char i[] /*= NULL*/,
const char doYouWantToFindSomethingInTheCommandLineIDidSomethingForYouToFindSomethingInTheCommandLineMaybeYouWillFindSomeInterestingInTheCommandLineSoIDidSomethingForYouInTheCommandLine[] /*= NULL*/,
unsigned x /*= 0*/)
{
// ...so tired of it already...
#define name i // Great name!
#define cmdLineSubstr doYouWantToFindSomethingInTheCommandLineIDidSomethingForYouToFindSomethingInTheCommandLineMaybeYouWillFindSomeInterestingInTheCommandLineSoIDidSomethingForYouInTheCommandLine
#define pid x // Another great name, isn't it?
$3 if (_TX_ARGUMENT_FAILED ((name || cmdLineSubstr || pid) && "Вот такие тут интересные имена встречаются...")) return false; //-V560 //-V601
$ wchar_t cmdLineSubstrW[_TX_BUFSIZE] = L"";
if (cmdLineSubstr) {$ MultiByteToWideChar (_TX_CODEPAGE, 0, cmdLineSubstr, -1, cmdLineSubstrW, sizearr (cmdLineSubstrW)); }
$ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
$ assert (sshot); if (!sshot) return 0; //-V547
$ int killed = 0;
$ PROCESSENTRY32 info = { sizeof (info) };
$ for (bool ok = !!Process32First (sshot, &info); ok; ok = !!Process32Next (sshot, &info))
{
bool kill = false;
if (!kill && pid && info.th32ParentProcessID == pid) {$ kill = true; } //-V560
if (!kill && name && _stricmp (info.szExeFile, name) == 0) {$ kill = true; }
if (!kill)
{
wchar_t cmdLineW[_TX_BUFSIZE] = L"";
if (!_txGetCommandLine (cmdLineW, sizearr (cmdLineW), info.th32ProcessID)) { continue; }
if (*cmdLineW && stristrw (cmdLineW, cmdLineSubstrW)) {$ kill = true; }
}
if (kill)
{
$ if (_txKillProcess (info.th32ProcessID))
{$ killed++; }
}
}
$ CloseHandle (sshot);
$ return killed;
#undef name
#undef cmdLine
#undef pid
}
//-----------------------------------------------------------------------------------------------------------------
bool _txKillProcess (DWORD pid)
{
$3 if (_TX_ARGUMENT_FAILED (pid)) return false;
$ HANDLE token = INVALID_HANDLE_VALUE;
$ OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) asserted;
$ LUID luid = {};
$ LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &luid) asserted;
$ TOKEN_PRIVILEGES priv = { 1, {{{ luid.LowPart, luid.HighPart}, SE_PRIVILEGE_ENABLED }}};
$ TOKEN_PRIVILEGES old = {};
$ DWORD oldSz = 0;
$ AdjustTokenPrivileges (token, false, &priv, sizeof (priv), &old, &oldSz) asserted;
$ HANDLE proc = OpenProcess (PROCESS_ALL_ACCESS, 0, pid);
$ if (!proc) return false;
$ bool ok = !!Win32::TerminateProcess (proc, 0);
$ CloseHandle (proc);
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
PROCESSENTRY32* _txFindProcess (unsigned pid /*= GetCurrentProcessId()*/)
{
$4 static PROCESSENTRY32 info = { sizeof (info) };
$ if (!pid) return &info;
$ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
$ assert (sshot); if (!sshot) return NULL; //-V547
$ for (bool ok = !!Process32First (sshot, &info); ok; ok = !!Process32Next (sshot, &info))
if (info.th32ProcessID == pid) break;
$ CloseHandle (sshot);
$ return &info;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txGetCommandLine (wchar_t cmdLine[], size_t szCmdLine, unsigned pid /*= _getpid()*/)
{
$6 if (_TX_ARGUMENT_FAILED (cmdLine)) return false;
$ if (_TX_ARGUMENT_FAILED (szCmdLine >= 2)) return false; //-V547
$ if (pid == (unsigned) _getpid())
{
$ wcsncpy_s (cmdLine, szCmdLine, GetCommandLineW(), szCmdLine-1);
$ return true;
}
$ HANDLE proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid);
if (!proc) {$ return false; }
$ Win32::PROCESS_BASIC_INFORMATION pbi = {};
$ bool ok = (Win32::NtQueryInformationProcess (proc, 0 /*ProcessBasicInformation*/, &pbi, sizeof (pbi), NULL) == 0);
// Should use ReadProcessMemory() because the info is actually in another address space
$ Win32::PEB peb = {};
if (ok && pbi.PebBaseAddress) {$ ok &= !!ReadProcessMemory (proc, pbi.PebBaseAddress, &peb, sizeof (peb), NULL); }
$ Win32::RTL_USER_PROCESS_PARAMETERS params = {};
if (ok && peb.ProcessParameters) {$ ok &= !!ReadProcessMemory (proc, peb.ProcessParameters, ¶ms, sizeof (params), NULL); }
$ *cmdLine = 0;
if (ok && params.CommandLine.Buffer) {$ ok &= !!ReadProcessMemory (proc, params.CommandLine.Buffer, cmdLine, //-V106
MIN (params.CommandLine.Length + 2, (int) (szCmdLine * sizeof (*cmdLine)) - 2), //-V202
NULL); }
$ CloseHandle (proc) asserted;
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
#define RVA_(type, module, addr) ( (type) ((uintptr_t) (module) + (uintptr_t) (addr)) )
IMAGE_NT_HEADERS* _txGetNtHeaders (HMODULE module /*= GetModuleHandle (NULL)*/)
{
$4 assert (module);
$ IMAGE_DOS_HEADER* dosHdr = RVA_ (IMAGE_DOS_HEADER*, module, 0);
$ IMAGE_NT_HEADERS* ntHdr = RVA_ (IMAGE_NT_HEADERS*, module, dosHdr->e_lfanew);
$ return (dosHdr->e_magic == IMAGE_DOS_SIGNATURE &&
ntHdr->Signature == IMAGE_NT_SIGNATURE)? ntHdr : NULL;
}
//-----------------------------------------------------------------------------------------------------------------
// TXLib continues to hack the reality to make your life better, sweeter and easier
uintptr_t _txSetProcAddress (const char funcName[], uintptr_t newFunc, const char dllName[] /*= NULL*/, int useHotPatching /*= false*/,
HMODULE module /*= NULL*/, bool debug /*= false*/)
{
$4 if (debug) txOutputDebugPrintf ("_txSetProcAddress (%s, 0x%p, %s, 0x%p):\n", funcName, (void*) newFunc, dllName, (void*) module);
$ if (_TX_ARGUMENT_FAILED (funcName)) return 0;
$ if (_TX_ARGUMENT_FAILED (newFunc)) return 0;
$ if (!module) module = GetModuleHandle (NULL);
$ if (!module) return 0;
$ HMODULE dll = (dllName)? GetModuleHandle (dllName) : NULL;
$ PROC oldFunc = (dll)? GetProcAddress (dll, funcName) : NULL;
$ if (useHotPatching && oldFunc)
{
$ const size_t jmpSz = 1 + sizeof (DWORD); // sizeof (JMP rel instruction)
$ DWORD oldRights = 0;
$ if (!VirtualProtect ((void*)(uintptr_t) oldFunc, jmpSz, PAGE_EXECUTE_READWRITE, &oldRights)) return 0;
// Overwrite oldFunc prolog with JMP trampoline to newFunc.
// Calling oldFunc from any location will lead to newFunc call anyway.
$ *(BYTE*) ((char*)(uintptr_t) oldFunc + 0) = 0xE9; // JMP rel
$ *(DWORD*) ((char*)(uintptr_t) oldFunc + 1) = ((char*)(uintptr_t) newFunc - (char*)(uintptr_t) oldFunc - jmpSz) & 0xFFFFFFFF; //-V206 //-V112 //-V2007 //-V104 //-V103
$ FlushInstructionCache (GetCurrentProcess(), (void*)(uintptr_t) oldFunc, jmpSz);
$ VirtualProtect ((void*)(uintptr_t) oldFunc, jmpSz, oldRights, &oldRights);
$ return (uintptr_t) oldFunc;
}
// For PE structure and Import Table format, e.g. see https://books.google.ru/books?id=ifQPC86G66sC&pg=PA255
// and below through Figure 5-5, and/or http://www.brokenthorn.com/Resources/OSDevPE.html.
$ IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders (module);
if (!ntHdr || (ntHdr ->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)) {$ return 0; }
$ DWORD impOffset = ntHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
$ IMAGE_IMPORT_DESCRIPTOR* desc = RVA_ (IMAGE_IMPORT_DESCRIPTOR*, module, impOffset);
$ if (desc == (IMAGE_IMPORT_DESCRIPTOR*) ntHdr) return 0; //-V1027
$ IMAGE_THUNK_DATA* thunk0 = NULL, * thunk1 = NULL;
$ char* impDll = NULL;
$ char* impName = NULL;
$ void** impPtr = NULL;
$ bool found = false;
for (; desc->Name; desc++)
{
$ impDll = RVA_ (char*, module, desc->Name);
$ if (dllName && _stricmp (impDll, dllName) != 0) continue;
$ for (thunk0 = RVA_ (IMAGE_THUNK_DATA*, module, desc->OriginalFirstThunk),
thunk1 = RVA_ (IMAGE_THUNK_DATA*, module, desc->FirstThunk);
thunk0 && thunk1 && thunk1->u1.Function;
thunk0++,
thunk1++)
{
impName = (char*) RVA_ (IMAGE_IMPORT_BY_NAME*, module, thunk0->u1.AddressOfData) -> Name;
impPtr = (void**)(uintptr_t) &thunk1->u1.Function; // Should change it, so this is ptr
if (IsBadReadPtr (impName, sizeof (impName))) impName = NULL;
if (debug) txOutputDebugPrintf ("[0x%p] %s!%s\n", *impPtr, impDll, impName);
if ((oldFunc && (uintptr_t) oldFunc == (uintptr_t) *impPtr) ||
(impName && _stricmp (funcName, impName) == 0)) //-V560
{
found = true;
break;
}
}
$ if (found) break;
}
if (debug) txOutputDebugPrintf ("_txSetProcAddress (%s, 0x%p, %s, 0x%p): %s\n\n",
funcName, (void*) newFunc, dllName, (void*) module, (found? "FOUND" : "NOT found"));
$ if (!found) return 0;
$ DWORD rights = PAGE_READWRITE;
$ if (!VirtualProtect (impPtr, sizeof (*impPtr), rights, &rights)) return 0;
$ *(uintptr_t*) impPtr = newFunc;
$ VirtualProtect (impPtr, sizeof (*impPtr), rights, &rights);
$ return (uintptr_t) oldFunc;
}
#undef RVA_
//-----------------------------------------------------------------------------------------------------------------
bool _txInDll()
{
$4 MODULEENTRY32 mod = { sizeof (mod) };
$ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
$ assert (sshot); if (!sshot) return false; //-V547
$ bool inDll = false;
$ for (bool ok = !!Module32First (sshot, &mod); ok; ok = !!Module32Next (sshot, &mod))
{
$ if (!mod.modBaseAddr) continue;
$ IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders ((HMODULE) mod.modBaseAddr);
$ inDll = ntHdr && ((ntHdr->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0);
$ if (In (std::nomeow, (BYTE*)(uintptr_t)_txInDll, mod.modBaseAddr, mod.modBaseAddr + mod.modBaseSize)) //-V104
{$ break; }
}
$ CloseHandle (sshot);
$ return inDll;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txIsConsoleSubsystem()
{
$4 IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders();
$ return ntHdr &&
ntHdr ->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC &&
(ntHdr ->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI ||
ntHdr ->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_POSIX_CUI);
}
//-----------------------------------------------------------------------------------------------------------------
bool _txIsBadReadPtr (const void* address)
{
MEMORY_BASIC_INFORMATION mbi = {};
if (!VirtualQuery (address, &mbi, sizeof (mbi))) return true;
if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) return true; // Guard page -> bad ptr
DWORD readRights = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
return !(mbi.Protect & readRights);
}
//-----------------------------------------------------------------------------------------------------------------
void _txActivateWindow (HWND wnd, unsigned mode)
{
$1 EnableWindow (wnd, true);
$ if (mode & 0x10)
{
$ ShowWindow (wnd, SW_MINIMIZE);
$ ShowWindow (wnd, SW_RESTORE);
}
$ if (mode & 0x08)
{
$ int focus = GetWindowThreadProcessId (GetForegroundWindow(), 0);
$ AttachThreadInput (GetCurrentThreadId(), focus, true);
$ SetForegroundWindow (wnd);
$ AttachThreadInput (GetCurrentThreadId(), focus, false);
}
$ if (mode & 0x04)
{
$ SetWindowPos (wnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
}
$ if (mode & 0x02)
{
$ SetWindowPos (wnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_ASYNCWINDOWPOS);
}
$ if (mode & 0x01)
{
$ UpdateWindow (wnd);
}
}
#endif // TX_COMPILED
//}
//-----------------------------------------------------------------------------------------------------------------
//! @}
//}
//=================================================================================================================
//=================================================================================================================
//{ Internal TXLib window functions (_txCanvas...)
//! @name Внутренние функции окна TXLib (_txCanvas...)
//=================================================================================================================
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
unsigned WINAPI _txCanvas_ThreadProc (void* data)
{
#define SetClassLong_ SetClassLongPtr
#define GCL_HICON_ GCLP_HICON
#define GCL_HICONSM_ GCLP_HICONSM
#define GCL_HCURSOR_ GCLP_HCURSOR
$8 _txCanvas_ThreadId = GetCurrentThreadId();
$ if (_TX_ARGUMENT_FAILED (data)) return false; //-V601
$ unsigned long stackSize = _TX_STACKSIZE;
$ _TX_CALL (Win32::SetThreadStackGuarantee, (&stackSize));
$ HWND wnd = _txCanvas_CreateWindow ((SIZE*) data);
$ if (!txWindow()) return TX_DEBUG_ERROR ("\a" "Cannot create canvas!"), 0;
$ HICON icon32 = LoadIcon (NULL, "_TX_ICON");
$ HICON icon16 = LoadIcon (NULL, "_TX_ICONSM");
$ HCURSOR cursor = LoadCursor (NULL, "_TX_CURSOR");
$ HMENU menu = LoadMenu (NULL, "_TX_MENU");
$ HACCEL accel = LoadAccelerators (NULL, "_TX_ACCELERATORS");
$ SetClassLong_ (wnd, GCL_HICON_, (LONG_PTR) (icon32? icon32 : _txCreateTXIcon (32))); //-V107 //-V112
$ SetClassLong_ (wnd, GCL_HICONSM_, (LONG_PTR) (icon16? icon16 : _txCreateTXIcon (16))); //-V107
$ SetClassLong_ (wnd, GCL_HCURSOR_, (LONG_PTR) (cursor? cursor : LoadCursor (NULL, IDC_ARROW))); //-V107
if (menu) {$ SetMenu (wnd, menu); DrawMenuBar (wnd); }
$ Win32::GdiSetBatchLimit (1);
_TX_ON_DEBUG (OutputDebugString (_TX_VERSION " - STARTED: " _TX_MODULE "\n"));
$ _txActivateWindow (wnd, 0x10);
$ ShowWindow (wnd, SW_SHOW);
$ UpdateWindow (wnd);
$ _txRunning = true;
$ MSG msg = {};
$ while (GetMessage (&msg, NULL, 0, 0))
{
if (!msg.hwnd) {$ continue; }
if (accel && TranslateAccelerator (wnd, accel, &msg)) {$ continue; }
$ TranslateMessage (&msg);
$ DispatchMessage (&msg);
$ Sleep (0);
}
$ if (icon16) DestroyIcon (icon16); // If Explorer is displaying Tray Notification, these
$ if (icon32) DestroyIcon (icon32); // calls will possibly fail, and we'll get resource leak.
$ LeaveCriticalSection (&_txCanvas_LockBackBuf);
_TX_ON_DEBUG (OutputDebugString (_TX_VERSION " - STOPPED: " _TX_MODULE "\n"));
$ if (_txWatchdogTimeout >= 0)
{$ Win32::_beginthread (_txWatchdogTerminator, 0, &_txWatchdogTimeout); }
$ if (_txRunning && _txMain) // Main window is destroyed but main() is still running.
{ // No chances for good termination, so use exit().
$ _txCleanup();
$ ::exit ((int) msg.wParam); //-V202 //-V2509 //-V2014
}
$ _txCanvas_ThreadId = 0;
$ return true; //-V601
#undef SetClassLong
#undef GCL_HICON_
#undef GCL_HICONSM_
#undef GCL_HCURSOR_
}
//-----------------------------------------------------------------------------------------------------------------
HWND _txCanvas_CreateWindow (const SIZE* sizePtr)
{
$8 if (_TX_ARGUMENT_FAILED (sizePtr)) return NULL;
$ bool centered = false;
if (sizePtr->cx < 0 && sizePtr->cy < 0) {$ centered = true; }
$ SIZE screen = { GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN) };
$ RECT rect = { 0, 0, abs (sizePtr->cx), abs (sizePtr->cy) }; AdjustWindowRect (&rect, _txWindowStyle, false);
$ SIZE size = { rect.right - rect.left, rect.bottom - rect.top };
$ RECT conPos = {};
$ HWND console = _TX_CALL (Win32::GetConsoleWindow, ());
if (console) {$ GetWindowRect (console, &conPos); }
$ const char* wndClass = txRegisterClass ("MAIN", _txCanvas_WndProc, CS_HREDRAW | CS_VREDRAW | CS_OWNDC, BLACK_BRUSH, 0);
$ if (!wndClass) return (HWND) NULL;
$ HWND wnd = CreateWindowEx (WS_EX_APPWINDOW, wndClass, txGetModuleFileName (false), _txWindowStyle | WS_CLIPCHILDREN,
(centered)? screen.cx/2 - size.cx/2 : (console)? conPos.left : CW_USEDEFAULT,
(centered)? screen.cy/2 - size.cy/2 : (console)? conPos.top : CW_USEDEFAULT,
size.cx, size.cy, NULL, NULL, NULL, NULL);
$ if (!wnd || !txWindow())
{$ return TX_DEBUG_ERROR ("Cannot create canvas: CreateWindowEx() failed"), (HWND) NULL; }
$ HMENU menu = GetSystemMenu (txWindow(), false);
if (!menu) {$ return txWindow(); }
$ AppendMenu (menu, MF_SEPARATOR, 0, NULL) asserted;
$ AppendMenu (menu, MF_STRING, _TX_IDM_CONSOLE, "Show &Console") asserted;
$ AppendMenu (menu, MF_STRING, _TX_IDM_ABOUT, "&About...") asserted;
$ return txWindow();
}
//-----------------------------------------------------------------------------------------------------------------
const char* txRegisterClass (const char classId[], WNDPROC wndProc, unsigned style, int backBrush, int wndExtra)
{
$8 assert (classId);
$ assert (wndProc);
$ static char name[_TX_BUFSIZE] = "";
$ _tx_snprintf_s (name, sizeof (name) - 1, "/*---[TXLib]-[%s]------------ "
_TX_VERSION " " __FILE__ " WndClass %08lX "
"-------------[%s]-[TXLib]---*/",
classId, (unsigned long) GetTickCount(), classId);
$ WNDCLASS wc = { sizeof (wc) };
$ wc.lpszClassName = name;
$ wc.lpfnWndProc = wndProc;
$ wc.style = style;
$ wc.cbWndExtra = (wndExtra + 1) * (int) sizeof (long);
$ wc.hCursor = LoadCursor (NULL, IDC_ARROW);
$ wc.hbrBackground = (HBRUSH) Win32::GetStockObject (backBrush);
$ ATOM atom = RegisterClass (&wc);
if (!atom) {$ TX_DEBUG_ERROR ("RegisterClass (\"%s\") failed", name); return 0; }
$ return (const char*)(uintptr_t) atom;
}
//-----------------------------------------------------------------------------------------------------------------
int _txCanvas_SetRefreshLock (int count)
{
$8 int oldCount = _txCanvas_RefreshLock;
$ _txCanvas_RefreshLock = count;
$ HWND wnd = txWindow();
$ if ((_txCanvas_RefreshLock <= 0 || oldCount <= 0) && wnd)
{$ RedrawWindow (wnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_UPDATENOW); }
$ return oldCount;
}
//-----------------------------------------------------------------------------------------------------------------
HICON _txCreateTXIcon (int size)
{
$8 if (_TX_ARGUMENT_FAILED (size == 32 || size == 16)) return NULL; //-V112 //-V560
$ const unsigned char image32 [32*32+1] =
"00000000000000000000000000000000""0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0""0F0000000000000000000000000000F0""0F0000000000000000000000000000F0"
"0F0000000000000099999999999900F0""0F0000000000000090300333330900F0""0F0000000990000090000000000900F0""0F00000099990000900BB000000900F0"
"0F0000039999000090B00090900900F0""0F0000009999000090B00999990900F0""0F00000009903799900BB090900900F0""0F000000009BB70090000010000900F0"
"0F0000000B90000090000000000900F0""0F000000B0B0000099999999999900F0""0F00007B30B0000090000000000000F0""0F00007300B0000090000000000000F0"
"0F00000000B3000090000000000000F0""0F0000000B0B000090000000000000F0""0F000000B303B00090000000000000F0""0F000003B000B00090000000000000F0"
"0F00003B00003B0090000000000000F0""0F0000300000030090000000000000F0""0F0000000448888888888844000000F0""0F00004886E6E6E60E66E6EEEE4400F0"
"0F4488866E0E60E00660E06E66EEE4F0""0F868806E06E06E666E66E00E06EE6F0""0F08606E66E0066000E006E66E00E6F0""0F8666E006600E00006600E006E00EF0"
"0F000E066888888888888888606660F0""0F66EEE6EE000E00000E00086EEEE6F0""0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0""00000000000000000000000000000000";
$ const unsigned char image16 [16*16+1] =
"0000000000000000""0000000999999990""0009000900000090""0099900909973090""0059700909009390""0009799909973090""0099000900000090""0959330999999990"
"0709500900000000""0095930900000000""0090393900000000""0790073900000000""0900000900000000""000EE6E6E6E6E000""0EE6E6E6E6E6EEE0""0000000000000000";
$ const COLORREF pal['F'-'0'+1] = { 0x000000, 0x002b2b, 0x555500, 0x005555, 0x808000, 0x008080, 0xaaaa00, 0x00aaaa, 0xd5d500, 0x00d5d5, 0,0,0,0,0,0,0,
0xffff00, 0x00ffff, 0xffffaa, 0xaaffff, 0xd5d500, 0xffffff };
$ const unsigned char* image = (size == 32)? image32 : image16; //-V112
$ POINT sz = { size, size };
$ HDC dcMask = _txBuffer_Create (txWindow(), &sz); assert (dcMask);
$ HDC dcColor = _txBuffer_Create (txWindow(), &sz); assert (dcColor);
$ for (int i = 0; i < size*size; i++)
{
assert (In (std::nomeow, image[i], '0', '9') ||
In (std::nomeow, image[i], 'A', 'F'));
Win32::SetPixel (dcColor, i % size, i / size, pal [image[i] - '0']);
}
$ ICONINFO info = { true, 0, 0, (HBITMAP) Win32::GetCurrentObject (dcMask, OBJ_BITMAP),
(HBITMAP) Win32::GetCurrentObject (dcColor, OBJ_BITMAP) };
$ HICON icon = CreateIconIndirect (&info);
$ assert (icon);
$ _txBuffer_Delete (&dcMask) asserted;
$ _txBuffer_Delete (&dcColor) asserted;
$ return icon;
}
#endif // TX_COMPILED
//-----------------------------------------------------------------------------------------------------------------
inline bool _txCanvas_OK()
{
return _txCanvas_ThreadId &&
_txCanvas_Window &&
_txCanvas_BackBuf[0] &&
_txCanvas_BackBuf[1] &&
_txCanvas_Pixels;
}
//}
//=================================================================================================================
//=================================================================================================================
//{ Main window event handlers (_txCanvas_On...)
//! @name События основного окна (_txCanvas_On...)
//=================================================================================================================
//! @{
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
LRESULT CALLBACK _txCanvas_WndProc (HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar)
{
#if defined (_TX_ALLOW_TRACE)
int inTX = _txLoc::Cur.inTX++;
if (_txLoc::Cur.trace) _txTrace (__FILE__, __LINE__, __TX_FUNCTION__, "%*s" "0x%X <- 0x%04X (0x%08X, 0x%08lX)",
2 * (_txLoc::Cur.inTX - 1), "", wnd, msg, wpar, lpar);
_txLoc::Cur.inTX = inTX;
#endif
$8 if (msg == WM_KEYDOWN && wpar == VK_F12 &&
GetKeyState (VK_SHIFT) && GetKeyState (VK_CONTROL) && GetKeyState (VK_MENU))
{
$ _txCanvas_OnCmdABOUT (wnd, wpar);
$ return DefWindowProc (wnd, msg, wpar, lpar);
}
WNDPROC altWndProc = _txAltWndProc; // Cache to prevent change from main thread
if (altWndProc)
{
$ LRESULT res = altWndProc (wnd, msg, wpar, lpar);
$ if (res) return res;
}
static bool bkErased = false;
switch (msg)
{
case WM_CREATE: {$ _txCanvas_OnCREATE (wnd); return 0; }
case WM_CLOSE: {$ if (_txCanvas_OnCLOSE (wnd)) break; else return 0; }
case WM_DESTROY: {$ _txCanvas_OnDESTROY (wnd); return 0; }
case WM_ERASEBKGND: {$ if (!bkErased) { bkErased = true; break; } else return 1; }
case WM_SIZE: {$ bkErased = false; break; }
case WM_PAINT: {$ _txCanvas_OnPAINT (wnd); return 0; }
case WM_TIMER: {$ _txCanvas_OnTIMER (wnd, wpar); return 0; }
case WM_KEYUP: {$ if (_txCanvas_OnKEY (wnd, wpar, lpar, false)) return 0; else break; }
case WM_KEYDOWN: {$ if (_txCanvas_OnKEY (wnd, wpar, lpar, true)) return 0; else break; }
case WM_CHAR: {$ if (_txCanvas_OnCHAR (wnd, wpar, lpar)) return 0; else break; }
case WM_LBUTTONUP:
case WM_LBUTTONDOWN:
case WM_RBUTTONUP:
case WM_RBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MOUSEMOVE: {$ _txCanvas_OnMOUSEMOVE (wnd, wpar, lpar); return 0; }
case WM_MOUSELEAVE: {$ _txCanvas_OnMOUSELEAVE (wnd); return 0; }
case _TX_WM_CREATEWND: {$ _txCanvas_OnCREATEWND (wnd, wpar, lpar); return 0; }
case _TX_WM_DESTROYWND: {$ _txCanvas_OnDESTROYWND (wnd, wpar, lpar); return 0; }
case WM_NULL: {$ return 0; }
default: break; //-V2522
}
if (msg == WM_SYSCOMMAND) switch (wpar)
{
case _TX_IDM_ABOUT: {$ _txCanvas_OnCmdABOUT (wnd, wpar); return 0; }
case _TX_IDM_CONSOLE: {$ _txCanvas_OnCmdCONSOLE (wnd, wpar); return 0; }
default: break; //-V2522
}
$ return DefWindowProc (wnd, msg, wpar, lpar);
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCREATE (HWND wnd)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ _txCanvas_BackBuf[0] = _txBuffer_Create (wnd, NULL, NULL, &_txCanvas_Pixels); assert (_txCanvas_BackBuf[0]);
$ _txCanvas_BackBuf[1] = _txBuffer_Create (wnd, NULL, NULL, NULL); assert (_txCanvas_BackBuf[1]);
$ if (!SetTimer (wnd, _txCanvas_RefreshTimer, _txWindowUpdateInterval, NULL)) _txCanvas_RefreshTimer = 0;
$ assert (_txCanvas_RefreshTimer);
$ _txCanvas_UserDCs = new ::std::vector <HDC>;
$ _txCanvas_Window = wnd;
$ txSetDefaults();
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnDESTROY (HWND wnd)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
// Инициируем остановку цикла сообщений
$ PostQuitMessage (_txRunning? WM_DESTROY : EXIT_SUCCESS);
$ if (!_txCanvas_Window) return false;
// Indicate that we are about to manually terminate
$ _txExit = true;
// Lock GDI resources
$ bool locked = false;
$ _txWaitFor ((locked = txLock (false), locked), _TX_TIMEOUT);
$ if (!locked) TX_DEBUG_ERROR ("Cannot lock GDI to free resources");
// Освобождаем пользовательские ресурсы
$ if (_txCanvas_UserDCs && !_txCanvas_UserDCs->empty())
{
$ txNotifyIcon (NIIF_ERROR, NULL, "Вы забыли освободить %d HDC.", (int) _txCanvas_UserDCs->size()); //-V202
$ Sleep (_TX_TIMEOUT);
$ for (size_t i = 0; i < _txCanvas_UserDCs->size(); i++) _txBuffer_Delete (&_txCanvas_UserDCs->at (i));
$ _txCanvas_UserDCs->clear();
}
// Освобождаем ресурсы, связанные с окном
$ if (_txCanvas_RefreshTimer) KillTimer (wnd, _txCanvas_RefreshTimer) asserted;
$ if (_txCanvas_BackBuf[1]) _txBuffer_Delete (&_txCanvas_BackBuf[1]) asserted;
$ if (_txCanvas_BackBuf[0]) _txBuffer_Delete (&_txCanvas_BackBuf[0]) asserted;
$ _txCanvas_Pixels = NULL;
$ txUnlock();
// Indicate that we are destroyed
$ _txCanvas_Window = NULL;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCLOSE (HWND wnd) //-V2009 //-V2558
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ if (!_txCanvas_OK()) return false;
$ if (_txMain && _txRunning &&
txMessageBox ("Функция main() не завершена. Программа все еще работает. Прервать аварийно?\n\n"
"Лучше подождать, когда main() завершится - это отображается в заголовке окна.",
txGetModuleFileName (false), MB_YESNOCANCEL | MB_ICONSTOP) != IDYES) return false;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnTIMER (HWND wnd, WPARAM)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ if (_txCanvas_RefreshLock > 0 || !_txRunning) return false;
$ InvalidateRect (wnd, NULL, false) asserted;
$ UpdateWindow (wnd) asserted;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnPAINT (HWND wnd)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ if (!_txCanvas_OK()) return false;
$ bool forceRedraw = GetAsyncKeyState (VK_MENU) && GetAsyncKeyState (VK_CONTROL) &&
GetAsyncKeyState (VK_SHIFT) && GetAsyncKeyState (VK_SNAPSHOT);
$ PAINTSTRUCT ps = {};
$ HDC wndDc = BeginPaint (wnd, &ps);
$ if (!wndDc) return false;
$ HDC dc0 = _txCanvas_BackBuf[0],
dc1 = _txCanvas_BackBuf[1];
$ RECT r = {};
$ GetClientRect (wnd, &r) asserted;
$ POINT wndSize = { r.right - r.left, r.bottom - r.top };
$ POINT dcSize = txGetExtent (dc1);
$ if ((_txCanvas_RefreshLock <= 0 || forceRedraw) &&
txLock (false))
{
$ Win32::BitBlt (dc1, 0, 0, dcSize.x, dcSize.y, dc0, 0, 0, SRCCOPY);
$ if (_txConsole >= 0)
{$ _txConsole_Draw (dc1); }
$ txUnlock();
}
// Magic 100500 value is used to completely block screen refresh.
// Since no value can be 100500 or above, this condition is always true and the refresh cannot be blocked IRL.
// Do not use 100501 because it may lead to errors on some compilers and possible may crash the compilers
// themselves.
// Yes guys, with all your software installed. :(
$ if (_txCanvas_RefreshLock != 100500)
{
if (_txSwapBuffers)
{
$ _txSwapBuffers (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, dcSize.x, dcSize.y, SRCCOPY);
}
else if (dcSize.x == wndSize.x && dcSize.y == wndSize.y)
{
$ Win32::BitBlt (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, SRCCOPY);
}
else
{
$ Win32::SetStretchBltMode (wndDc, HALFTONE);
$ Win32::StretchBlt (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, dcSize.x, dcSize.y, SRCCOPY);
}
}
$ EndPaint (wnd, &ps) asserted;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCHAR (HWND, WPARAM ch, LPARAM info)
{
$8 INPUT_RECORD evt[2] = {};
$ evt[0].EventType = KEY_EVENT;
$ evt[0].Event.KeyEvent.bKeyDown = true;
$ evt[0].Event.KeyEvent.wRepeatCount = 1;
$ evt[0].Event.KeyEvent.uChar.AsciiChar = (char) (ch);
$ evt[0].Event.KeyEvent.wVirtualScanCode = (WORD) (info >> 16);
$ evt[0].Event.KeyEvent.wVirtualKeyCode = (WORD) MapVirtualKey ((WORD) (info >> 16), 3); // 3 == MAPVK_VSC_TO_VK_EX
$ evt[0].Event.KeyEvent.dwControlKeyState = 0;
$ evt[1] = evt[0];
$ evt[1].Event.KeyEvent.bKeyDown = false;
$ DWORD written = 0;
$ WriteConsoleInput (GetStdHandle (STD_INPUT_HANDLE), evt, 2, &written);
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnKEY (HWND, WPARAM vk, LPARAM info, bool down)
{
$8 INPUT_RECORD evt = {};
$ evt.EventType = KEY_EVENT;
$ evt.Event.KeyEvent.bKeyDown = down;
$ evt.Event.KeyEvent.wRepeatCount = 1;
$ evt.Event.KeyEvent.uChar.AsciiChar = (char) MapVirtualKey ((WORD) vk, 2); // 2 == MAPVK_VK_TO_CHAR
$ evt.Event.KeyEvent.wVirtualScanCode = (WORD) (info >> 16);
$ evt.Event.KeyEvent.wVirtualKeyCode = (WORD) vk;
$ evt.Event.KeyEvent.dwControlKeyState = (DWORD) (info & (1 << (24-1)))? ENHANCED_KEY : 0;
$ if (evt.Event.KeyEvent.uChar.AsciiChar) return false; // Let TranslateMessage() and WM_CHAR do the job
$ DWORD written = 0;
$ WriteConsoleInput (GetStdHandle (STD_INPUT_HANDLE), &evt, 1, &written);
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnMOUSEMOVE (HWND wnd, WPARAM buttons, LPARAM coords)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ if (!_txCanvas_OK()) return false;
$ if (_txMousePos.x == -1 && _txMousePos.y == -1)
{
$ TRACKMOUSEEVENT track = { sizeof (track), TME_HOVER | TME_LEAVE, wnd, HOVER_DEFAULT };
$ TrackMouseEvent (&track);
}
$ _txMousePos.x = LOWORD (coords);
$ _txMousePos.y = HIWORD (coords);
$ _txMouseButtons = (unsigned) buttons; //-V202
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnMOUSELEAVE (HWND)
{
$8 _txMousePos.x = -1;
$ _txMousePos.y = -1;
$ _txMouseButtons = 0;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCREATEWND (HWND, WPARAM, LPARAM lpar)
{
$8 if (_TX_ARGUMENT_FAILED (lpar)) return false;
$ const CREATESTRUCT* create = (CREATESTRUCT*) lpar;
$ HWND wnd = CreateWindowEx (create->dwExStyle, create->lpszClass, create->lpszName, create->style,
create->x, create->y, create->cx, create->cy,
create->hwndParent, create->hMenu, NULL, create->lpCreateParams);
$ *(HWND*) create->hInstance = wnd;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnDESTROYWND (HWND, WPARAM, LPARAM lpar)
{
$8 if (_TX_ARGUMENT_FAILED (lpar)) return false;
$ DestroyWindow ((HWND) lpar);
$ return false;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCmdCONSOLE (HWND wnd, WPARAM cmd)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ HWND console = Win32::GetConsoleWindow();
$ if (!console) return false;
$ bool visible = !!IsWindowVisible (console);
$ ShowWindow (console, visible? SW_HIDE : SW_RESTORE);
$ visible = !!IsWindowVisible (console);
$ CheckMenuItem (GetSystemMenu (wnd, false), (int) cmd, visible? MF_CHECKED : MF_UNCHECKED); //-V202
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCmdABOUT (HWND, WPARAM)
{
$8 //{ Overriding the missing names, if the set is uncomplete
#if defined (__MODULE)
#define ABOUT_NAME_ __MODULE
#else
#define ABOUT_NAME_ "TXLib"
#endif
#if defined (__MODULE) || defined (__VERSION) || defined (__DESCRIPTION) || defined (__AUTHOR)
#ifndef __MODULE
#define __MODULE "TXLib" "\n" "#define __MODULE to set the name.\n"
#endif
#ifndef __VERSION
#define __VERSION "(0.000000000)." "\n" "#define __VERSION to set the string value.\n"
#endif
#ifndef __DESCRIPTION
#define __DESCRIPTION "(Да, мне лень задать описание)." "\n" "#define __DESCRIPTION to override project role.\n"
#endif
#ifndef __AUTHOR
#define __AUTHOR "(Непонятно кто)." "\n" "#define __AUTHOR to override this name."
#endif
#endif
//}
$ static char text[_TX_BUFSIZE] = "";
$ _tx_snprintf_s (text, sizeof (text) - 1,
"Application:\n\n"
#if defined (__MODULE) || defined (__VERSION) || defined (__DESCRIPTION) || defined (__AUTHOR)
__MODULE " version " __VERSION "\n" __DESCRIPTION "\n" "Copyright (c) " __AUTHOR "\n"
#else
"Здесь могла бы быть Ваша реклама :)\n"
"#define __MODULE to \"your program name\" before including TXLib.h to use this billboard...\n"
#endif
"\n" "%s", _txAppInfo());
$ txMessageBox (text, "About " ABOUT_NAME_, MB_ICONINFORMATION);
// And a bit of HTTP-code in C++ function:
goto http;
http://sizeof.livejournal.com
$ return true;
#undef ABOUT_NAME_
}
#endif // TX_COMPILED
//! @}
//}
//=================================================================================================================
//=================================================================================================================
//{ Console-support functions (_txConsole...)
//! @name Функции консольного окна (_txConsole...)
//=================================================================================================================
//! @{
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
HWND _txConsole_Attach()
{
$1 HWND console = Win32::GetConsoleWindow();
$ if (!console)
{
$ bool minimizeConsole = ((TX_CONSOLE_MODE) == SW_HIDE && !_txIsConsoleSubsystem());
$ Win32::TEB* teb = (Win32::TEB*) NtCurrentTeb();
$ assert (teb);
$ assert (teb->ProcessEnvironmentBlock);
$ Win32::RTL_USER_PROCESS_PARAMETERS* params = teb->ProcessEnvironmentBlock->ProcessParameters;
$ assert (params);
$ if (minimizeConsole) // The fact that ShowWindow parameter of the program's console is taken from calling
// process' STARTUPINFO, was researched from Windows XP sources. See SetUpConsoleInfo()
// in windows\core\ntcon\client\dllinit.c. No one can miss stealing Windows sources. :(
// Thank you Matt Pietrek, the author of "Undocumented Windows". Use the Source, Luke!..
{
$ params->dwFlags |= STARTF_USESHOWWINDOW;
$ params->wShowWindow = SW_MINIMIZE;
}
$ AllocConsole();
$ console = Win32::GetConsoleWindow();
}
$ if (!console) return NULL;
$ txSetLocale(); // Устанавливаем русскую кодовую страницу для консоли Windows
$ _txConsole_SetUnicodeFont(); // Впечатлительным лучше сюда не смотреть.
$ if (!_txIsConsoleSubsystem())
{$ txReopenStdio(); } // Переоткрываем потоки ввода-вывода, если subsystem != console
$ return console;
}
//-----------------------------------------------------------------------------------------------------------------
int txSetLocale (int codepage /*= _TX_CODEPAGE*/,
const char locale[] /*= _TX_LOCALE*/, const wchar_t wLocale[] /*= _TX_WLOCALE*/)
{
$1 int oldPage = GetConsoleOutputCP();
// Устанавливаем нужную кодовую страницу для консоли Windows
$ if (codepage)
{
$ SetConsoleCP (codepage);
$ SetConsoleOutputCP (codepage);
}
// Устанавливаем нужную кодовую страницу для стандартной библиотеки, иначе не будут работать Unicode-версии
// функций (wprintf, ...). Если компилите с помощью gcc и собираетесь использовать L"unicode-строки" с определенным
// языком, укажите опции в командной строке компилятора g++: -finput-charset=NNNN -fexec-charset=NNNN, где NNNN -
// обозначение кодовой страницы (например, для русского языка - CP1251).
$ if (locale)
{
$ setlocale (LC_ALL, locale);
$ setlocale (LC_NUMERIC, "C"); // Return to decimal point (3.14) instead of comma (3,14) in floating numbers
}
#ifndef __CYGWIN__
$ const bool wine = !!Win32::wine_get_version; // Linux::Wine v1.2.2+ compatibility.
$ if (wLocale && !wine)
{
$ _wsetlocale (LC_ALL, wLocale);
$ _wsetlocale (LC_NUMERIC, L"C"); // L"C" (see above)
}
#endif
(void) wLocale;
$ return oldPage;
}
//-----------------------------------------------------------------------------------------------------------------
void txReopenStdio()
{
$1 // Переоткрываем заново <s>Америку) [0])
8567 case 192: {$ codePage = 1251; sCodePage =
"1251.";
break; }
8568 case 208: {$ codePage = 65001; sCodePage =
"UTF-8.";
break; }
8569 case 128: {$ codePage = 866; sCodePage =
"866.";
break; }
8570 case 225: {$ codePage = 20866; sCodePage =
"KOI-8, waaat?!";
break; }
8571 default: {$ codePage = -1; sCodePage =
"(Unknown)";
break; }
8574 $
if (codePage != needCP && verbose)
8576 $ *_txTraceSE =
' ';
8578 $ _TX_UNEXPECTED (
"\v\t" "\n\n" "WARNING: CHECK TXLib.h file CODEPAGE. Maybe it is %s It should be %d.\n\n"
8579 "This is NOT an error of TXLib itself. Please note:\n\n"
8580 "Do NOT copy-and-paste TXLib.h file contents into a new file and them save it inside your "
8581 "IDE or editor. This can change original TXLib codepage (%d) to another one. Instead, DO "
8582 "use copy / move / cut-and-paste operations in Windows Explorer (Far Manager etc) only. "
8583 "Or, when you see TXLib.h being opened in browser, use 'Save as...' (Ctrl+S) command.\n\n"
8584 "Now you should re-download TXLib.h file from the http://txlib.ru site.\n\n"
8585 "You can continue, but Russian messages and symbols may appear unreadable.",
8586 sCodePage, needCP, needCP);
8589 $
return (codePage == needCP);
8594 void (*_txDllImport (
const char dllFileName[],
const char funcName[],
bool required )) ()
8596 if (_TX_ARGUMENT_FAILED (dllFileName && *dllFileName))
return NULL;
8597 if (_TX_ARGUMENT_FAILED (funcName && *funcName))
return NULL;
8599 static char dllPaths [2][MAX_PATH] = {
"",
""};
8603 const char dllDir[] =
"\\Windows\\";
8607 char* path = dllPaths[0];
8609 txRegQuery (
"HKCU\\Software\\TX Library",
"ProductDir", path, MAX_PATH);
8610 strncat_s (path, MAX_PATH, dllDir,
sizeof (dllDir) - 1);
8616 if (strchr (__FILE__,
':'))
8618 strncpy_s (path, MAX_PATH, __FILE__,
sizeof (__FILE__) - 1);
8622 GetCurrentDirectory (MAX_PATH, path);
8623 strncat_s (path, MAX_PATH,
"\\" __FILE__,
sizeof (
"\\" __FILE__) - 1);
8626 if (
char* dir = strrchr (path,
'\\')) *dir = 0;
8628 strncat_s (path, MAX_PATH, dllDir,
sizeof (dllDir) - 1);
8631 char dllName[MAX_PATH] =
"", dllArch[MAX_PATH] =
"";
8632 const char* arch = (dllFileName? strchr (dllFileName,
'*') : NULL);
8636 assert (arch >= dllFileName);
8638 strncpy_s (dllName,
sizeof (dllName), dllFileName, (
size_t) (arch - dllFileName));
8639 strncat_s (dllName,
sizeof (dllName), arch+1,
sizeof (dllName) - 1 - strlen (dllName));
8641 strncpy_s (dllArch,
sizeof (dllArch), dllFileName, (
size_t) (arch - dllFileName));
8642 strncat_s (dllArch,
sizeof (dllArch),
sizeof (
void*) == 8?
"64" :
"32", 3);
8643 strncat_s (dllArch,
sizeof (dllArch), arch+1,
sizeof (dllArch) - 1 - strlen (dllArch));
8645 else if (dllFileName)
8647 strncat_s (dllName,
sizeof (dllName), dllFileName,
sizeof (dllName) - 1);
8650 HMODULE dll = GetModuleHandle (dllFileName);
8652 if (!dll) dll = GetModuleHandle (dllArch);
8653 if (!dll) dll = GetModuleHandle (dllName);
8655 for (
int i = 0; !dll && i < (int)
sizearr (dllPaths); i++)
8657 char path [MAX_PATH] =
"";
8658 strncpy_s (path,
sizeof (path), dllPaths[i],
sizeof (dllPaths[i]));
8659 size_t len = strlen (path);
8661 strncpy_s (path + len,
sizeof (path) - len, dllArch,
sizeof (dllArch));
8662 if (!dll) dll = LoadLibrary (path);
8664 strncpy_s (path + len,
sizeof (path) - len, dllName,
sizeof (dllName));
8665 if (!dll) dll = LoadLibrary (path);
8668 if (!dll) dll = LoadLibrary (dllArch);
8669 if (!dll) dll = LoadLibrary (dllName);
8671 if (!dll && required)
TX_ERROR (
"\a" "Cannot load library \"%s%s%s\".",
8672 dllName, (arch?
"\" / \"" :
""), dllArch);
8673 if (!dll)
return NULL;
8675 void (*addr)() = (
void(*)()) GetProcAddress (dll, funcName);
8677 if (!addr && required)
TX_ERROR (
"\a" "Cannot import \"%s\" from library \"%s%s%s\".",
8678 funcName, dllName, (arch?
"\" / \"" :
""), dllArch);
8684 #if defined (_MSC_VER) && (_MSC_VER == 1800)
8685 #pragma warning (push)
8686 #pragma warning (disable: 6102)
8689 int txRegQuery (
const char* keyName,
const char* valueName,
void* value,
size_t szValue)
8691 if (_TX_ARGUMENT_FAILED (keyName))
return 0;
8695 #define EQU_(name1, name2) ( _strnicmp (keyName, name1 "\\", sizeof (name1)) == 0 || \
8696 _strnicmp (keyName, name2 "\\", sizeof (name2)) == 0 )
8698 if (EQU_(
"HKLM",
"HKEY_LOCAL_MACHINE")) hive = HKEY_LOCAL_MACHINE;
8699 else if (EQU_(
"HKCU",
"HKEY_CURRENT_USER")) hive = HKEY_CURRENT_USER;
8700 else if (EQU_(
"HKCR",
"HKEY_CLASSES_ROOT")) hive = HKEY_CLASSES_ROOT;
8701 else if (EQU_(
"HKU",
"HKEY_USERS")) hive = HKEY_USERS;
8702 else if (EQU_(
"HKCC",
"HKEY_CURRENT_CONFIG")) hive = HKEY_CURRENT_CONFIG;
8704 else { _TX_ARGUMENT_FAILED ((
"keyName должно начинаться с HKLM\\, HKCU\\, HKCR\\, HKU\\ или HKCC\\ ", hive));
return 0; }
8708 keyName = strchr (keyName,
'\\') + 1;
8709 assert (keyName > (
const char*) 1);
8714 bool ok = (RegOpenKeyEx (hive, keyName, 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS);
8715 if (ok) ok &= (RegQueryValueEx (key, valueName, NULL, NULL, NULL, &size) == ERROR_SUCCESS);
8716 if (ok && value && size < szValue) ok &= (RegQueryValueEx (key, valueName, NULL, NULL, (BYTE*) value, &size) == ERROR_SUCCESS);
8717 if (key) ok &= (RegCloseKey (key) == ERROR_SUCCESS);
8722 #if defined (_MSC_VER) && (_MSC_VER == 1800)
8723 #pragma warning (pop)
8735 $1
if (!_txInitialized) _txInitialized = _txInitialize();
8739 $ SetLastErrorEx (ERROR_INVALID_DATA, 0);
8740 $ _TX_ON_DEBUG (
TX_ERROR (
"\a" "Окно рисования уже создано!"));
8746 $ _txMain = ! FindAtom (
"_txMain");
8747 $ (void) AddAtom (
"_txMain");
8752 $ _txRunning =
false;
8756 $
static SIZE size = {
ROUND (sizeX),
ROUND (sizeY) };
8757 $
if (centered) { size.cx *= -1; size.cy *= -1; }
8762 $ _txCanvas_Thread = (HANDLE) Win32::_beginthreadex (NULL, 0, _txCanvas_ThreadProc, &size, 0, &
id);
8764 $
if (!_txCanvas_Thread)
return TX_DEBUG_ERROR (
"\a" "Cannot start canvas thread."), (HWND) NULL;
8768 $
if (!_txRunning)
return TX_DEBUG_ERROR (
"\a" "Cannot create canvas window."), (HWND) NULL;
8771 $ HWND console = Win32::GetConsoleWindow();
8774 $ GetWindowThreadProcessId (console, &proc);
8776 $
if (console && (proc == GetCurrentProcessId() || _txIsParentWaitable()))
8779 $ HMENU menu = GetSystemMenu (
txWindow(),
false);
8780 if (menu) {$ CheckMenuItem (menu, _TX_IDM_CONSOLE, (console? (IsWindowVisible (console)? MF_CHECKED : 0) : MF_DISABLED)); }
8782 $ Win32::GdiSetBatchLimit (1);
8788 #if !defined (__CYGWIN__)
8797 HWND txCreateExtraWindow (CREATESTRUCT createData)
8799 $1
if (_TX_TXWINDOW_FAILED())
return NULL;
8801 $
volatile HWND wnd = NULL;
8802 $ createData.hInstance = (HINSTANCE)(uintptr_t) &wnd;
8804 $ PostMessage (
txWindow(), _TX_WM_CREATEWND, 0, (LPARAM) &createData)
asserted;
8819 $ GetClientRect (Win32::GetConsoleWindow(), &r);
8820 $ SIZE szCon = { r.right - r.left, r.bottom - r.top };
8822 $ HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
8824 $ CONSOLE_SCREEN_BUFFER_INFO con = {{80, 25}, {}, 0, {0, 0, 80-1, 25-1}, {80, 25}};
8825 $ GetConsoleScreenBufferInfo (out, &con);
8827 $ SIZE szTxt = { (short) (con.srWindow.Right - con.srWindow.Left + 1),
8828 (short) (con.srWindow.Bottom - con.srWindow.Top + 1) };
8832 $ _txBuffer_Select (Win32::GetStockObject (WHITE_PEN), dc)
asserted;
8833 $ _txBuffer_Select (Win32::GetStockObject (WHITE_BRUSH), dc)
asserted;
8835 $ _txBuffer_Select (Win32::CreateFont (szCon.cy/szTxt.cy, szCon.cx/szTxt.cx,
8836 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
8837 RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
8842 $ Win32::SetBkMode (dc, TRANSPARENT)
asserted;
8844 $ Win32::SetROP2 (dc, R2_COPYPEN)
asserted;
8845 $ Win32::SetStretchBltMode (dc, HALFTONE)
asserted;
8857 Win32::CreateFont (szCanvas.y/szTxt.cy, szCanvas.x/szTxt.cx,
8858 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
8859 RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
8862 Win32::GetStockObject (SYSTEM_FIXED_FONT);
8864 $ _txBuffer_Select (font, _txCanvas_BackBuf[1]);
8869 $
if (con.dwCursorPosition.X) _putch (
'\n');
8871 $
short delta = (short) (con.dwCursorPosition.Y - con.srWindow.Top);
8873 $ con.srWindow.Top = (short) (con.srWindow.Top + delta);
8874 $ con.srWindow.Bottom = (short) (con.srWindow.Bottom + delta);
8876 $ SMALL_RECT src = { 0, 0, (short) (con.dwSize.X - 1), (short) (con.dwSize.Y - 1) };
8877 $ CHAR_INFO fill = { {
' '}, FOREGROUND_LIGHTGRAY };
8878 $ COORD dest = { 0, (short) -delta };
8880 $ con.dwCursorPosition.X = 0;
8881 $ con.dwCursorPosition.Y = (short) (con.dwCursorPosition.Y - delta);
8883 $ (con.srWindow.Bottom < con.dwSize.Y &&
8884 SetConsoleWindowInfo (out,
true, &con.srWindow))
8886 (ScrollConsoleScreenBuffer (out, &src, NULL, dest, &fill),
8887 SetConsoleCursorPosition (out, con.dwCursorPosition));
8901 return (_txCanaryFirst == 0x776F656D &&
8902 _txCanaryLast == 0x5E2E2E5E &&
8905 #
if defined (_MSC_VER)
8906 && _CrtCheckMemory()
8923 OutputDebugString (
"\n");
8927 _TX_CALLv (Win32::_cexit, ());
8932 void _txOnExit (
int retcode)
8936 OutputDebugString (
"\n");
8945 Win32::exit (retcode);
8950 void _txOnExitProcess (
unsigned retcode)
8954 OutputDebugString (
"\n");
8961 txOutputDebugPrintf (
"%s - WARNING: calling Win32::ExitProcess (%u)\n", _TX_VERSION, retcode);
8963 Win32::ExitProcess (retcode);
8968 bool _txOnTerminateProcess (HANDLE process,
unsigned retcode)
8972 OutputDebugString (
"\n");
8973 txOutputDebugPrintf (
"%s - WARNING: %s (0x%p, %u) called\n", _TX_VERSION, __func__, process, retcode);
8979 txOutputDebugPrintf (
"%s - WARNING: calling Win32::TerminateProcess (0x%p, %u)\n", _TX_VERSION, process, retcode);
8981 return Win32::TerminateProcess (process, retcode);
8986 void _txOnFatalExit (
int retcode)
8988 OutputDebugString (
"\n");
8993 txOutputDebugPrintf (
"%s - WARNING: calling Win32::FatalExit (%d)\n", _TX_VERSION, retcode);
8994 _TX_CALLv (Win32::FatalExit, (retcode));
8996 txOutputDebugPrintf (
"%s - WARNING: Win32::FatalExit() failure, calling Win32::TerminateProcess (%d)\n", _TX_VERSION, retcode);
8997 Win32::TerminateProcess (GetCurrentProcess(), retcode);
9002 void _txOnFatalAppExitA (
unsigned action,
const char message[])
9004 OutputDebugString (
"\n");
9005 txOutputDebugPrintf (
"%s - WARNING: %s (%u, \"%s\") called\n", _TX_VERSION, __func__, action, message);
9009 txOutputDebugPrintf (
"%s - WARNING: calling Win32::FatalAppExitA (%u, %s)\n", _TX_VERSION, action, message);
9010 _TX_CALLv (Win32::FatalAppExitA, (action, message));
9012 txOutputDebugPrintf (
"%s - WARNING: Win32::FatalExit() failure, calling Win32::TerminateProcess (EXIT_FAILURE)\n", _TX_VERSION);
9013 Win32::TerminateProcess (GetCurrentProcess(), EXIT_FAILURE);
9018 BOOL WINAPI _txOnConsoleCtrlEvent (DWORD type)
9020 OutputDebugString (
"\n");
9021 txOutputDebugPrintf (
"%s - WARNING: %s (0x%04lX) called\n", _TX_VERSION, __func__, (
unsigned long) type);
9025 case CTRL_LOGOFF_EVENT:
9026 case CTRL_SHUTDOWN_EVENT: $ _txExit =
true;
9029 case CTRL_CLOSE_EVENT:
9030 case CTRL_BREAK_EVENT:
9042 if (!_txInitialized)
return;
9043 else _txInitialized =
false;
9045 $3 _txRunning =
false;
9046 $ _txConsole_IsBlinking =
false;
9048 $
txSetProgress (100, (!_txErrors)? Win32::TBPF_PAUSED : Win32::TBPF_ERROR);
9053 $ HWND console = Win32::GetConsoleWindow();
9054 $
unsigned thread = GetCurrentThreadId();
9056 $ HWND wnd = (canvas)? canvas : console;
9058 $
bool externTerm = (thread != _txMainThreadId &&
9059 thread != _txCanvas_ThreadId);
9062 $
int isParentWaitable = _txIsParentWaitable (&parent);
9063 $
bool waitableParent = !externTerm && isParentWaitable;
9074 $ EnableWindow (console,
true);
9075 $ _txSetWindowText (console,
" [ЗАВЕРШЕНО]",
" [FINISHED]", 2, L
"\x0417" L
"\x0046" );
9079 $
if (_txMain && !externTerm && canvas)
9080 {$ _txSetWindowText (canvas,
" [ЗАВЕРШЕНО]",
" [FINISHED]", 2, L
"\x0417" L
"\x0046" ); }
9082 $ std::cout.flush();
9083 $ std::cerr.flush();
9084 $ std::clog.flush();
9087 $
bool paused =
false;
9088 $
if (((canvas? _txMain : _txConsole) && !_txExit) || (_txErrors && thread == _txMainThreadId))
9092 $
if (isParentWaitable >= 0)
9093 {$ _txActivateWindow (wnd, 0x08); }
9095 $ EnableWindow (wnd,
true);
9098 $
if (console && isParentWaitable >= 0)
9100 $
txPause ((_txErrors)?
"\f\n" "[Press F to Pay Respects...]" :
9101 (!canvas && _txIsTTY (0))?
"\f\n" "[Нажмите любую клавишу для завершения]" :
"\f");
9111 {$ SendNotifyMessage (
txWindow(), WM_DESTROY, 0, 0); }
9118 $
delete _txCanvas_UserDCs;
9119 $ _txCanvas_UserDCs = NULL;
9121 $
if (GetCurrentThreadId() != _txMainThreadId)
9122 {$ SuspendThread (_txMainThread); }
9123 $
if (GetCurrentThreadId() != _txCanvas_ThreadId)
9124 {$ SuspendThread (_txCanvas_Thread); }
9126 $
if (_txMainThread)
9127 {$ CloseHandle (_txMainThread)
asserted; _txMainThread = NULL; }
9128 $
if (_txCanvas_Thread)
9129 {$ CloseHandle (_txCanvas_Thread)
asserted; _txCanvas_Thread = NULL; }
9132 {$ DeleteCriticalSection (&_txCanvas_LockBackBuf); CRITICAL_SECTION zero = {0, -1}; _txCanvas_LockBackBuf = zero; }
9134 $
bool parentKilled =
false;
9137 $ console = Win32::GetConsoleWindow();
9140 {$ parentKilled = _txKillProcess (parent); }
9142 $
if (parent && !parentKilled)
9144 $ PostMessage (console, WM_KEYDOWN, VK_RETURN, 0x001C0001);
9145 $ PostMessage (console, WM_KEYUP, VK_RETURN, 0xC01C0001);
9150 {$ _txSetWindowText (console, NULL); }
9152 $
if (_txMain && _txConsole)
9153 {$ _txConsole_Detach (waitableParent && !parentKilled && !externTerm); }
9155 $ std::cout.flush();
9156 $ std::cerr.flush();
9157 $ std::clog.flush();
9160 $ _txSymGetFromAddr (NULL);
9164 _TX_ON_DEBUG (OutputDebugString (
"\n");
9165 OutputDebugString (_TX_VERSION
" - FINISHED: " _TX_MODULE "\n");
9166 OutputDebugString (
"\n"));
9171 int txPause (
const char* message , ...)
9173 $3
bool wine = !!Win32::wine_get_version;
9176 $ HWND console = Win32::GetConsoleWindow();
9177 $ HWND wnd = (canvas)? canvas : console;
9178 $
bool istty0 = _txIsTTY (0);
9182 $
int oldCP = GetConsoleOutputCP();
9185 if (!message) {$ message =
"[Нажмите любую клавишу для продолжения]"; }
9187 if (*message !=
'\f') {$ _txSetWindowText (wnd,
" [Нажмите клавишу...]",
" [Press a key...]"); }
9188 else {$ message++; }
9191 else {$ message++; }
9193 $ _txActivateWindow (wnd, 0x08);
9196 $ va_start (args, message);
9197 $ vfprintf (stderr, message, args);
9204 $ Win32::FLASHWINFO flash = {
sizeof (flash), wnd, FLASHW_ALL | FLASHW_TIMERNOFG, 0xFFFFFFFF };
9205 $ _TX_CALL (Win32::FlashWindowEx, (&flash));
9208 if (istty0) {$
while (!wine && _kbhit()) ch = _getch(); }
9210 $
for (
int i = 1; ; i++)
9214 if (!istty0 && !canvas) {$
break; }
9216 if (!wine && (ch = _txGetInput()) != EOF) {$
break; }
9218 if (canvas && !_txCanvas_ThreadId) {$
break; }
9220 if (!Win32::GetConsoleWindow()) {$
break; }
9222 if (_TX_CALL (Win32::GhostWindowFromHungWindow, (canvas)))
9223 {$
TX_ERROR (
"Похоже, программа зависла :(");
break; }
9225 if (canvas && _TX_CALL (Win32::IsHungAppWindow, (canvas)))
9226 {$ _txTrace (__FILE__, __LINE__, NULL,
"WARNING: Программа-таки зависла ); break; }
if (canvas && !SendMessageTimeout (canvas, WM_NULL, 0,0, SMTO_BLOCK | SMTO_ABORTIFHUNG, _TX_TIMEOUT, NULL))
{$ _txTrace (__FILE__, __LINE__, NULL, "WARNING: Программа не отвечает"); break; }
if (!wine && !(i % 100500))
{$ fprintf (stderr, "\r" "[Так нажмите же какую-нибудь клавишу...] \b\b"); }
}
if (istty0) {$ while (!wine && _kbhit()) ch = _getch(); }
$ _txSetWindowText (wnd, NULL);
$ fprintf (stderr, "\n");
if (ch == 3 /* Ctrl+C */) {$ raise (SIGABRT); }
$ SetConsoleOutputCP (oldCP);
$ txSetConsoleAttr (attr);
$ return ch;
}
//-----------------------------------------------------------------------------------------------------------------
int _txGetInput()
{
$4 HANDLE con = GetStdHandle (STD_INPUT_HANDLE);
$ int ch = EOF;
$ DWORD nChars = 0;
$ if (GetConsoleMode (con, &nChars) == 0 &&
PeekNamedPipe (con, NULL, 0, NULL, &nChars, NULL))
{
$ ch = (nChars)? fgetc (stdin) : EOF;
}
else if (_kbhit())
{
$ ch = _getch();
}
#if defined (_MSC_VER) && (_MSC_VER < 1700)
else if (fseek (stdin, 1, SEEK_CUR) != EOF)
{
$ (void) fseek (stdin, -1, SEEK_CUR);
$ ch = fgetc (stdin); // This causes blocking in MSVC 2011 beta
}
#endif
if (ch == 3 /* Ctrl+C */) {$ raise (SIGABRT); }
$ return ch;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txIsTTY (int fd)
{
$4 return GetFileType ((HANDLE)_get_osfhandle (fd)) == FILE_TYPE_CHAR;
}
//-----------------------------------------------------------------------------------------------------------------
int _txSetWindowText (HWND wnd, const char* textRus, const char* textEng /*= NULL*/,
int checkOfs /*= 0*/, const wchar_t checkLetters[2] /*= NULL*/)
{
struct tools
{
static LRESULT getWindowText (HWND window, wchar_t text[], size_t size)
{
$3 memset (text, 0, size * sizeof (*text));
$ return SendMessageTimeoutW (window, WM_GETTEXT, (WPARAM) size, (LPARAM) text, SMTO_BLOCK | SMTO_ABORTIFHUNG, _TX_TIMEOUT, NULL);
}
static LRESULT setWindowText (HWND window, wchar_t text[])
{
$1 return SendMessageTimeoutW (window, WM_SETTEXT, 0, (LPARAM) text, SMTO_BLOCK | SMTO_ABORTIFHUNG, _TX_TIMEOUT, NULL);
}
};
$1 static wchar_t _tx_thread title [_TX_BUFSIZE+15] = L"TXLib";
$ static wchar_t _tx_thread oldTitle [_TX_BUFSIZE+15] = L"TXLib";
$ if (!textRus)
{
$ tools::setWindowText (wnd, oldTitle);
$ return -1;
}
$ tools::getWindowText (wnd, title, _TX_BUFSIZE-1);
$ int len = (int) wcslen (title); if (len >= (int)_TX_BUFSIZE) len = _TX_BUFSIZE-1;
$ memcpy (oldTitle, title, sizeof (oldTitle));
$ if (textRus)
{
$ MultiByteToWideChar (_TX_CODEPAGE, 0, textRus, -1, title + len, (int)_TX_BUFSIZE - len);
$ tools::setWindowText (wnd, title);
$ tools::getWindowText (wnd, title, _TX_BUFSIZE-1);
if (checkLetters && len <= (int)_TX_BUFSIZE-1-2 && title [len + checkOfs] == checkLetters[0]) {$ return 0; }
if (!checkLetters) {$ return -2; }
}
$ if (textEng)
{
$ MultiByteToWideChar (_TX_CODEPAGE, 0, textEng, -1, title + len, (int)_TX_BUFSIZE - len);
$ tools::setWindowText (wnd, title);
$ tools::getWindowText (wnd, title, _TX_BUFSIZE-1);
if (checkLetters && len <= (int)_TX_BUFSIZE-1-2 && title [len + checkOfs] == checkLetters[1]) {$ return 1; }
if (!checkLetters) {$ return -2; }
}
$ return -3;
}
//-----------------------------------------------------------------------------------------------------------------
int _txIsParentWaitable (DWORD* parentPID /*= NULL*/)
{
$4 PROCESSENTRY32* info = _txFindProcess();
$ if (!info) return 0;
$ info = _txFindProcess (info->th32ParentProcessID);
$ if (!info) return 0;
$ char parent [MAX_PATH] = "";
$ strncpy_s (parent, sizeof (parent), info->szExeFile, sizeof (parent) - 1);
$ if (parentPID) *parentPID = info->th32ProcessID;
$ info = _txFindProcess (info->th32ParentProcessID); // info: grandparent
$ char list[_TX_BUFSIZE] = _TX_WAITABLE_PARENTS;
$ char* ctx = NULL;
$ for (char* p = strtok_s (list, ", ", &ctx); p; p = strtok_s (NULL, ", ", &ctx))
{
$ char* gp = strchr (p, ':');
$ if (gp)
{
$ *gp++ = 0;
$ if (_stricmp (p, parent) != 0) { continue; }
$ if (info) if (_stricmp (gp, info->szExeFile) == 0) // Was &&, but MSVC /analyze is so paranoid
{$ return islower ((unsigned char) *gp)? +1 : -1; }
}
else
{
$ if (_stricmp (p, parent) == 0)
{$ return islower ((unsigned char) *p)? +1 : -1; }
}
}
$ return 0;
}
//-----------------------------------------------------------------------------------------------------------------
void _txWatchdogTerminator (void* timeout) // Or Watchcat? Possibly will change in future versions
{
$3 if (_TX_ARGUMENT_FAILED (timeout)) return;
$ Sleep (*(int*) timeout); //-V206
$ OutputDebugString ("\n");
txOutputDebugPrintf ("%s - WARNING: %s(): Timeout (%d) expired, activating. %s\n", // Kinda static reflection...
_TX_VERSION, __func__, *(int*) timeout, ((__func__[8] == 'd')? "Bark, bark" : "Meow, meow")); //-V206
$ DWORD parent = 0;
$ if (_txIsParentWaitable (&parent))
{
txOutputDebugPrintf ("%s - WARNING: %s(): Calling _txKillProcess (0x%04lu)\n",
_TX_VERSION, __func__, (unsigned long) parent);
$ _txKillProcess (parent);
$ HWND console = GetConsoleWindow();
$ PostMessage (console, WM_KEYDOWN, VK_RETURN, 0x001C0001); // Scancode = 0x1C, Count = 1
$ PostMessage (console, WM_KEYUP, VK_RETURN, 0xC01C0001); // Scancode = 0x1C, Count = 1, Prev = 1, Trans = 1
}
txOutputDebugPrintf ("%s - WARNING: %s(): Calling Win32::TerminateProcess (EXIT_FAILURE)\n", _TX_VERSION, __func__);
$ Win32::TerminateProcess (GetCurrentProcess(), EXIT_FAILURE);
}
#endif // TX_COMPILED
//}
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//{ Tools
//-----------------------------------------------------------------------------------------------------------------
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
// You are here, little hacker?
int _txTaskKill (const char i[] /*= NULL*/,
const char doYouWantToFindSomethingInTheCommandLineIDidSomethingForYouToFindSomethingInTheCommandLineMaybeYouWillFindSomeInterestingInTheCommandLineSoIDidSomethingForYouInTheCommandLine[] /*= NULL*/,
unsigned x /*= 0*/)
{
// ...so tired of it already...
#define name i // Great name!
#define cmdLineSubstr doYouWantToFindSomethingInTheCommandLineIDidSomethingForYouToFindSomethingInTheCommandLineMaybeYouWillFindSomeInterestingInTheCommandLineSoIDidSomethingForYouInTheCommandLine
#define pid x // Another great name, isn't it?
$3 if (_TX_ARGUMENT_FAILED ((name || cmdLineSubstr || pid) && "Вот такие тут интересные имена встречаются...")) return false; //-V560 //-V601
$ wchar_t cmdLineSubstrW[_TX_BUFSIZE] = L"";
if (cmdLineSubstr) {$ MultiByteToWideChar (_TX_CODEPAGE, 0, cmdLineSubstr, -1, cmdLineSubstrW, sizearr (cmdLineSubstrW)); }
$ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
$ assert (sshot); if (!sshot) return 0; //-V547
$ int killed = 0;
$ PROCESSENTRY32 info = { sizeof (info) };
$ for (bool ok = !!Process32First (sshot, &info); ok; ok = !!Process32Next (sshot, &info))
{
bool kill = false;
if (!kill && pid && info.th32ParentProcessID == pid) {$ kill = true; } //-V560
if (!kill && name && _stricmp (info.szExeFile, name) == 0) {$ kill = true; }
if (!kill)
{
wchar_t cmdLineW[_TX_BUFSIZE] = L"";
if (!_txGetCommandLine (cmdLineW, sizearr (cmdLineW), info.th32ProcessID)) { continue; }
if (*cmdLineW && stristrw (cmdLineW, cmdLineSubstrW)) {$ kill = true; }
}
if (kill)
{
$ if (_txKillProcess (info.th32ProcessID))
{$ killed++; }
}
}
$ CloseHandle (sshot);
$ return killed;
#undef name
#undef cmdLine
#undef pid
}
//-----------------------------------------------------------------------------------------------------------------
bool _txKillProcess (DWORD pid)
{
$3 if (_TX_ARGUMENT_FAILED (pid)) return false;
$ HANDLE token = INVALID_HANDLE_VALUE;
$ OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) asserted;
$ LUID luid = {};
$ LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &luid) asserted;
$ TOKEN_PRIVILEGES priv = { 1, {{{ luid.LowPart, luid.HighPart}, SE_PRIVILEGE_ENABLED }}};
$ TOKEN_PRIVILEGES old = {};
$ DWORD oldSz = 0;
$ AdjustTokenPrivileges (token, false, &priv, sizeof (priv), &old, &oldSz) asserted;
$ HANDLE proc = OpenProcess (PROCESS_ALL_ACCESS, 0, pid);
$ if (!proc) return false;
$ bool ok = !!Win32::TerminateProcess (proc, 0);
$ CloseHandle (proc);
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
PROCESSENTRY32* _txFindProcess (unsigned pid /*= GetCurrentProcessId()*/)
{
$4 static PROCESSENTRY32 info = { sizeof (info) };
$ if (!pid) return &info;
$ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
$ assert (sshot); if (!sshot) return NULL; //-V547
$ for (bool ok = !!Process32First (sshot, &info); ok; ok = !!Process32Next (sshot, &info))
if (info.th32ProcessID == pid) break;
$ CloseHandle (sshot);
$ return &info;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txGetCommandLine (wchar_t cmdLine[], size_t szCmdLine, unsigned pid /*= _getpid()*/)
{
$6 if (_TX_ARGUMENT_FAILED (cmdLine)) return false;
$ if (_TX_ARGUMENT_FAILED (szCmdLine >= 2)) return false; //-V547
$ if (pid == (unsigned) _getpid())
{
$ wcsncpy_s (cmdLine, szCmdLine, GetCommandLineW(), szCmdLine-1);
$ return true;
}
$ HANDLE proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid);
if (!proc) {$ return false; }
$ Win32::PROCESS_BASIC_INFORMATION pbi = {};
$ bool ok = (Win32::NtQueryInformationProcess (proc, 0 /*ProcessBasicInformation*/, &pbi, sizeof (pbi), NULL) == 0);
// Should use ReadProcessMemory() because the info is actually in another address space
$ Win32::PEB peb = {};
if (ok && pbi.PebBaseAddress) {$ ok &= !!ReadProcessMemory (proc, pbi.PebBaseAddress, &peb, sizeof (peb), NULL); }
$ Win32::RTL_USER_PROCESS_PARAMETERS params = {};
if (ok && peb.ProcessParameters) {$ ok &= !!ReadProcessMemory (proc, peb.ProcessParameters, ¶ms, sizeof (params), NULL); }
$ *cmdLine = 0;
if (ok && params.CommandLine.Buffer) {$ ok &= !!ReadProcessMemory (proc, params.CommandLine.Buffer, cmdLine, //-V106
MIN (params.CommandLine.Length + 2, (int) (szCmdLine * sizeof (*cmdLine)) - 2), //-V202
NULL); }
$ CloseHandle (proc) asserted;
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
#define RVA_(type, module, addr) ( (type) ((uintptr_t) (module) + (uintptr_t) (addr)) )
IMAGE_NT_HEADERS* _txGetNtHeaders (HMODULE module /*= GetModuleHandle (NULL)*/)
{
$4 assert (module);
$ IMAGE_DOS_HEADER* dosHdr = RVA_ (IMAGE_DOS_HEADER*, module, 0);
$ IMAGE_NT_HEADERS* ntHdr = RVA_ (IMAGE_NT_HEADERS*, module, dosHdr->e_lfanew);
$ return (dosHdr->e_magic == IMAGE_DOS_SIGNATURE &&
ntHdr->Signature == IMAGE_NT_SIGNATURE)? ntHdr : NULL;
}
//-----------------------------------------------------------------------------------------------------------------
// TXLib continues to hack the reality to make your life better, sweeter and easier
uintptr_t _txSetProcAddress (const char funcName[], uintptr_t newFunc, const char dllName[] /*= NULL*/, int useHotPatching /*= false*/,
HMODULE module /*= NULL*/, bool debug /*= false*/)
{
$4 if (debug) txOutputDebugPrintf ("_txSetProcAddress (%s, 0x%p, %s, 0x%p):\n", funcName, (void*) newFunc, dllName, (void*) module);
$ if (_TX_ARGUMENT_FAILED (funcName)) return 0;
$ if (_TX_ARGUMENT_FAILED (newFunc)) return 0;
$ if (!module) module = GetModuleHandle (NULL);
$ if (!module) return 0;
$ HMODULE dll = (dllName)? GetModuleHandle (dllName) : NULL;
$ PROC oldFunc = (dll)? GetProcAddress (dll, funcName) : NULL;
$ if (useHotPatching && oldFunc)
{
$ const size_t jmpSz = 1 + sizeof (DWORD); // sizeof (JMP rel instruction)
$ DWORD oldRights = 0;
$ if (!VirtualProtect ((void*)(uintptr_t) oldFunc, jmpSz, PAGE_EXECUTE_READWRITE, &oldRights)) return 0;
// Overwrite oldFunc prolog with JMP trampoline to newFunc.
// Calling oldFunc from any location will lead to newFunc call anyway.
$ *(BYTE*) ((char*)(uintptr_t) oldFunc + 0) = 0xE9; // JMP rel
$ *(DWORD*) ((char*)(uintptr_t) oldFunc + 1) = ((char*)(uintptr_t) newFunc - (char*)(uintptr_t) oldFunc - jmpSz) & 0xFFFFFFFF; //-V206 //-V112 //-V2007 //-V104 //-V103
$ FlushInstructionCache (GetCurrentProcess(), (void*)(uintptr_t) oldFunc, jmpSz);
$ VirtualProtect ((void*)(uintptr_t) oldFunc, jmpSz, oldRights, &oldRights);
$ return (uintptr_t) oldFunc;
}
// For PE structure and Import Table format, e.g. see https://books.google.ru/books?id=ifQPC86G66sC&pg=PA255
// and below through Figure 5-5, and/or http://www.brokenthorn.com/Resources/OSDevPE.html.
$ IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders (module);
if (!ntHdr || (ntHdr ->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)) {$ return 0; }
$ DWORD impOffset = ntHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
$ IMAGE_IMPORT_DESCRIPTOR* desc = RVA_ (IMAGE_IMPORT_DESCRIPTOR*, module, impOffset);
$ if (desc == (IMAGE_IMPORT_DESCRIPTOR*) ntHdr) return 0; //-V1027
$ IMAGE_THUNK_DATA* thunk0 = NULL, * thunk1 = NULL;
$ char* impDll = NULL;
$ char* impName = NULL;
$ void** impPtr = NULL;
$ bool found = false;
for (; desc->Name; desc++)
{
$ impDll = RVA_ (char*, module, desc->Name);
$ if (dllName && _stricmp (impDll, dllName) != 0) continue;
$ for (thunk0 = RVA_ (IMAGE_THUNK_DATA*, module, desc->OriginalFirstThunk),
thunk1 = RVA_ (IMAGE_THUNK_DATA*, module, desc->FirstThunk);
thunk0 && thunk1 && thunk1->u1.Function;
thunk0++,
thunk1++)
{
impName = (char*) RVA_ (IMAGE_IMPORT_BY_NAME*, module, thunk0->u1.AddressOfData) -> Name;
impPtr = (void**)(uintptr_t) &thunk1->u1.Function; // Should change it, so this is ptr
if (IsBadReadPtr (impName, sizeof (impName))) impName = NULL;
if (debug) txOutputDebugPrintf ("[0x%p] %s!%s\n", *impPtr, impDll, impName);
if ((oldFunc && (uintptr_t) oldFunc == (uintptr_t) *impPtr) ||
(impName && _stricmp (funcName, impName) == 0)) //-V560
{
found = true;
break;
}
}
$ if (found) break;
}
if (debug) txOutputDebugPrintf ("_txSetProcAddress (%s, 0x%p, %s, 0x%p): %s\n\n",
funcName, (void*) newFunc, dllName, (void*) module, (found? "FOUND" : "NOT found"));
$ if (!found) return 0;
$ DWORD rights = PAGE_READWRITE;
$ if (!VirtualProtect (impPtr, sizeof (*impPtr), rights, &rights)) return 0;
$ *(uintptr_t*) impPtr = newFunc;
$ VirtualProtect (impPtr, sizeof (*impPtr), rights, &rights);
$ return (uintptr_t) oldFunc;
}
#undef RVA_
//-----------------------------------------------------------------------------------------------------------------
bool _txInDll()
{
$4 MODULEENTRY32 mod = { sizeof (mod) };
$ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
$ assert (sshot); if (!sshot) return false; //-V547
$ bool inDll = false;
$ for (bool ok = !!Module32First (sshot, &mod); ok; ok = !!Module32Next (sshot, &mod))
{
$ if (!mod.modBaseAddr) continue;
$ IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders ((HMODULE) mod.modBaseAddr);
$ inDll = ntHdr && ((ntHdr->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0);
$ if (In (std::nomeow, (BYTE*)(uintptr_t)_txInDll, mod.modBaseAddr, mod.modBaseAddr + mod.modBaseSize)) //-V104
{$ break; }
}
$ CloseHandle (sshot);
$ return inDll;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txIsConsoleSubsystem()
{
$4 IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders();
$ return ntHdr &&
ntHdr ->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC &&
(ntHdr ->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI ||
ntHdr ->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_POSIX_CUI);
}
//-----------------------------------------------------------------------------------------------------------------
bool _txIsBadReadPtr (const void* address)
{
MEMORY_BASIC_INFORMATION mbi = {};
if (!VirtualQuery (address, &mbi, sizeof (mbi))) return true;
if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) return true; // Guard page -> bad ptr
DWORD readRights = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
return !(mbi.Protect & readRights);
}
//-----------------------------------------------------------------------------------------------------------------
void _txActivateWindow (HWND wnd, unsigned mode)
{
$1 EnableWindow (wnd, true);
$ if (mode & 0x10)
{
$ ShowWindow (wnd, SW_MINIMIZE);
$ ShowWindow (wnd, SW_RESTORE);
}
$ if (mode & 0x08)
{
$ int focus = GetWindowThreadProcessId (GetForegroundWindow(), 0);
$ AttachThreadInput (GetCurrentThreadId(), focus, true);
$ SetForegroundWindow (wnd);
$ AttachThreadInput (GetCurrentThreadId(), focus, false);
}
$ if (mode & 0x04)
{
$ SetWindowPos (wnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
}
$ if (mode & 0x02)
{
$ SetWindowPos (wnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_ASYNCWINDOWPOS);
}
$ if (mode & 0x01)
{
$ UpdateWindow (wnd);
}
}
#endif // TX_COMPILED
//}
//-----------------------------------------------------------------------------------------------------------------
//! @}
//}
//=================================================================================================================
//=================================================================================================================
//{ Internal TXLib window functions (_txCanvas...)
//! @name Внутренние функции окна TXLib (_txCanvas...)
//=================================================================================================================
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
unsigned WINAPI _txCanvas_ThreadProc (void* data)
{
#define SetClassLong_ SetClassLongPtr
#define GCL_HICON_ GCLP_HICON
#define GCL_HICONSM_ GCLP_HICONSM
#define GCL_HCURSOR_ GCLP_HCURSOR
$8 _txCanvas_ThreadId = GetCurrentThreadId();
$ if (_TX_ARGUMENT_FAILED (data)) return false; //-V601
$ unsigned long stackSize = _TX_STACKSIZE;
$ _TX_CALL (Win32::SetThreadStackGuarantee, (&stackSize));
$ HWND wnd = _txCanvas_CreateWindow ((SIZE*) data);
$ if (!txWindow()) return TX_DEBUG_ERROR ("\a" "Cannot create canvas!"), 0;
$ HICON icon32 = LoadIcon (NULL, "_TX_ICON");
$ HICON icon16 = LoadIcon (NULL, "_TX_ICONSM");
$ HCURSOR cursor = LoadCursor (NULL, "_TX_CURSOR");
$ HMENU menu = LoadMenu (NULL, "_TX_MENU");
$ HACCEL accel = LoadAccelerators (NULL, "_TX_ACCELERATORS");
$ SetClassLong_ (wnd, GCL_HICON_, (LONG_PTR) (icon32? icon32 : _txCreateTXIcon (32))); //-V107 //-V112
$ SetClassLong_ (wnd, GCL_HICONSM_, (LONG_PTR) (icon16? icon16 : _txCreateTXIcon (16))); //-V107
$ SetClassLong_ (wnd, GCL_HCURSOR_, (LONG_PTR) (cursor? cursor : LoadCursor (NULL, IDC_ARROW))); //-V107
if (menu) {$ SetMenu (wnd, menu); DrawMenuBar (wnd); }
$ Win32::GdiSetBatchLimit (1);
_TX_ON_DEBUG (OutputDebugString (_TX_VERSION " - STARTED: " _TX_MODULE "\n"));
$ _txActivateWindow (wnd, 0x10);
$ ShowWindow (wnd, SW_SHOW);
$ UpdateWindow (wnd);
$ _txRunning = true;
$ MSG msg = {};
$ while (GetMessage (&msg, NULL, 0, 0))
{
if (!msg.hwnd) {$ continue; }
if (accel && TranslateAccelerator (wnd, accel, &msg)) {$ continue; }
$ TranslateMessage (&msg);
$ DispatchMessage (&msg);
$ Sleep (0);
}
$ if (icon16) DestroyIcon (icon16); // If Explorer is displaying Tray Notification, these
$ if (icon32) DestroyIcon (icon32); // calls will possibly fail, and we'll get resource leak.
$ LeaveCriticalSection (&_txCanvas_LockBackBuf);
_TX_ON_DEBUG (OutputDebugString (_TX_VERSION " - STOPPED: " _TX_MODULE "\n"));
$ if (_txWatchdogTimeout >= 0)
{$ Win32::_beginthread (_txWatchdogTerminator, 0, &_txWatchdogTimeout); }
$ if (_txRunning && _txMain) // Main window is destroyed but main() is still running.
{ // No chances for good termination, so use exit().
$ _txCleanup();
$ ::exit ((int) msg.wParam); //-V202 //-V2509 //-V2014
}
$ _txCanvas_ThreadId = 0;
$ return true; //-V601
#undef SetClassLong
#undef GCL_HICON_
#undef GCL_HICONSM_
#undef GCL_HCURSOR_
}
//-----------------------------------------------------------------------------------------------------------------
HWND _txCanvas_CreateWindow (const SIZE* sizePtr)
{
$8 if (_TX_ARGUMENT_FAILED (sizePtr)) return NULL;
$ bool centered = false;
if (sizePtr->cx < 0 && sizePtr->cy < 0) {$ centered = true; }
$ SIZE screen = { GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN) };
$ RECT rect = { 0, 0, abs (sizePtr->cx), abs (sizePtr->cy) }; AdjustWindowRect (&rect, _txWindowStyle, false);
$ SIZE size = { rect.right - rect.left, rect.bottom - rect.top };
$ RECT conPos = {};
$ HWND console = _TX_CALL (Win32::GetConsoleWindow, ());
if (console) {$ GetWindowRect (console, &conPos); }
$ const char* wndClass = txRegisterClass ("MAIN", _txCanvas_WndProc, CS_HREDRAW | CS_VREDRAW | CS_OWNDC, BLACK_BRUSH, 0);
$ if (!wndClass) return (HWND) NULL;
$ HWND wnd = CreateWindowEx (WS_EX_APPWINDOW, wndClass, txGetModuleFileName (false), _txWindowStyle | WS_CLIPCHILDREN,
(centered)? screen.cx/2 - size.cx/2 : (console)? conPos.left : CW_USEDEFAULT,
(centered)? screen.cy/2 - size.cy/2 : (console)? conPos.top : CW_USEDEFAULT,
size.cx, size.cy, NULL, NULL, NULL, NULL);
$ if (!wnd || !txWindow())
{$ return TX_DEBUG_ERROR ("Cannot create canvas: CreateWindowEx() failed"), (HWND) NULL; }
$ HMENU menu = GetSystemMenu (txWindow(), false);
if (!menu) {$ return txWindow(); }
$ AppendMenu (menu, MF_SEPARATOR, 0, NULL) asserted;
$ AppendMenu (menu, MF_STRING, _TX_IDM_CONSOLE, "Show &Console") asserted;
$ AppendMenu (menu, MF_STRING, _TX_IDM_ABOUT, "&About...") asserted;
$ return txWindow();
}
//-----------------------------------------------------------------------------------------------------------------
const char* txRegisterClass (const char classId[], WNDPROC wndProc, unsigned style, int backBrush, int wndExtra)
{
$8 assert (classId);
$ assert (wndProc);
$ static char name[_TX_BUFSIZE] = "";
$ _tx_snprintf_s (name, sizeof (name) - 1, "/*---[TXLib]-[%s]------------ "
_TX_VERSION " " __FILE__ " WndClass %08lX "
"-------------[%s]-[TXLib]---*/",
classId, (unsigned long) GetTickCount(), classId);
$ WNDCLASS wc = { sizeof (wc) };
$ wc.lpszClassName = name;
$ wc.lpfnWndProc = wndProc;
$ wc.style = style;
$ wc.cbWndExtra = (wndExtra + 1) * (int) sizeof (long);
$ wc.hCursor = LoadCursor (NULL, IDC_ARROW);
$ wc.hbrBackground = (HBRUSH) Win32::GetStockObject (backBrush);
$ ATOM atom = RegisterClass (&wc);
if (!atom) {$ TX_DEBUG_ERROR ("RegisterClass (\"%s\") failed", name); return 0; }
$ return (const char*)(uintptr_t) atom;
}
//-----------------------------------------------------------------------------------------------------------------
int _txCanvas_SetRefreshLock (int count)
{
$8 int oldCount = _txCanvas_RefreshLock;
$ _txCanvas_RefreshLock = count;
$ HWND wnd = txWindow();
$ if ((_txCanvas_RefreshLock <= 0 || oldCount <= 0) && wnd)
{$ RedrawWindow (wnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_UPDATENOW); }
$ return oldCount;
}
//-----------------------------------------------------------------------------------------------------------------
HICON _txCreateTXIcon (int size)
{
$8 if (_TX_ARGUMENT_FAILED (size == 32 || size == 16)) return NULL; //-V112 //-V560
$ const unsigned char image32 [32*32+1] =
"00000000000000000000000000000000""0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0""0F0000000000000000000000000000F0""0F0000000000000000000000000000F0"
"0F0000000000000099999999999900F0""0F0000000000000090300333330900F0""0F0000000990000090000000000900F0""0F00000099990000900BB000000900F0"
"0F0000039999000090B00090900900F0""0F0000009999000090B00999990900F0""0F00000009903799900BB090900900F0""0F000000009BB70090000010000900F0"
"0F0000000B90000090000000000900F0""0F000000B0B0000099999999999900F0""0F00007B30B0000090000000000000F0""0F00007300B0000090000000000000F0"
"0F00000000B3000090000000000000F0""0F0000000B0B000090000000000000F0""0F000000B303B00090000000000000F0""0F000003B000B00090000000000000F0"
"0F00003B00003B0090000000000000F0""0F0000300000030090000000000000F0""0F0000000448888888888844000000F0""0F00004886E6E6E60E66E6EEEE4400F0"
"0F4488866E0E60E00660E06E66EEE4F0""0F868806E06E06E666E66E00E06EE6F0""0F08606E66E0066000E006E66E00E6F0""0F8666E006600E00006600E006E00EF0"
"0F000E066888888888888888606660F0""0F66EEE6EE000E00000E00086EEEE6F0""0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0""00000000000000000000000000000000";
$ const unsigned char image16 [16*16+1] =
"0000000000000000""0000000999999990""0009000900000090""0099900909973090""0059700909009390""0009799909973090""0099000900000090""0959330999999990"
"0709500900000000""0095930900000000""0090393900000000""0790073900000000""0900000900000000""000EE6E6E6E6E000""0EE6E6E6E6E6EEE0""0000000000000000";
$ const COLORREF pal['F'-'0'+1] = { 0x000000, 0x002b2b, 0x555500, 0x005555, 0x808000, 0x008080, 0xaaaa00, 0x00aaaa, 0xd5d500, 0x00d5d5, 0,0,0,0,0,0,0,
0xffff00, 0x00ffff, 0xffffaa, 0xaaffff, 0xd5d500, 0xffffff };
$ const unsigned char* image = (size == 32)? image32 : image16; //-V112
$ POINT sz = { size, size };
$ HDC dcMask = _txBuffer_Create (txWindow(), &sz); assert (dcMask);
$ HDC dcColor = _txBuffer_Create (txWindow(), &sz); assert (dcColor);
$ for (int i = 0; i < size*size; i++)
{
assert (In (std::nomeow, image[i], '0', '9') ||
In (std::nomeow, image[i], 'A', 'F'));
Win32::SetPixel (dcColor, i % size, i / size, pal [image[i] - '0']);
}
$ ICONINFO info = { true, 0, 0, (HBITMAP) Win32::GetCurrentObject (dcMask, OBJ_BITMAP),
(HBITMAP) Win32::GetCurrentObject (dcColor, OBJ_BITMAP) };
$ HICON icon = CreateIconIndirect (&info);
$ assert (icon);
$ _txBuffer_Delete (&dcMask) asserted;
$ _txBuffer_Delete (&dcColor) asserted;
$ return icon;
}
#endif // TX_COMPILED
//-----------------------------------------------------------------------------------------------------------------
inline bool _txCanvas_OK()
{
return _txCanvas_ThreadId &&
_txCanvas_Window &&
_txCanvas_BackBuf[0] &&
_txCanvas_BackBuf[1] &&
_txCanvas_Pixels;
}
//}
//=================================================================================================================
//=================================================================================================================
//{ Main window event handlers (_txCanvas_On...)
//! @name События основного окна (_txCanvas_On...)
//=================================================================================================================
//! @{
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
LRESULT CALLBACK _txCanvas_WndProc (HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar)
{
#if defined (_TX_ALLOW_TRACE)
int inTX = _txLoc::Cur.inTX++;
if (_txLoc::Cur.trace) _txTrace (__FILE__, __LINE__, __TX_FUNCTION__, "%*s" "0x%X <- 0x%04X (0x%08X, 0x%08lX)",
2 * (_txLoc::Cur.inTX - 1), "", wnd, msg, wpar, lpar);
_txLoc::Cur.inTX = inTX;
#endif
$8 if (msg == WM_KEYDOWN && wpar == VK_F12 &&
GetKeyState (VK_SHIFT) && GetKeyState (VK_CONTROL) && GetKeyState (VK_MENU))
{
$ _txCanvas_OnCmdABOUT (wnd, wpar);
$ return DefWindowProc (wnd, msg, wpar, lpar);
}
WNDPROC altWndProc = _txAltWndProc; // Cache to prevent change from main thread
if (altWndProc)
{
$ LRESULT res = altWndProc (wnd, msg, wpar, lpar);
$ if (res) return res;
}
static bool bkErased = false;
switch (msg)
{
case WM_CREATE: {$ _txCanvas_OnCREATE (wnd); return 0; }
case WM_CLOSE: {$ if (_txCanvas_OnCLOSE (wnd)) break; else return 0; }
case WM_DESTROY: {$ _txCanvas_OnDESTROY (wnd); return 0; }
case WM_ERASEBKGND: {$ if (!bkErased) { bkErased = true; break; } else return 1; }
case WM_SIZE: {$ bkErased = false; break; }
case WM_PAINT: {$ _txCanvas_OnPAINT (wnd); return 0; }
case WM_TIMER: {$ _txCanvas_OnTIMER (wnd, wpar); return 0; }
case WM_KEYUP: {$ if (_txCanvas_OnKEY (wnd, wpar, lpar, false)) return 0; else break; }
case WM_KEYDOWN: {$ if (_txCanvas_OnKEY (wnd, wpar, lpar, true)) return 0; else break; }
case WM_CHAR: {$ if (_txCanvas_OnCHAR (wnd, wpar, lpar)) return 0; else break; }
case WM_LBUTTONUP:
case WM_LBUTTONDOWN:
case WM_RBUTTONUP:
case WM_RBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MOUSEMOVE: {$ _txCanvas_OnMOUSEMOVE (wnd, wpar, lpar); return 0; }
case WM_MOUSELEAVE: {$ _txCanvas_OnMOUSELEAVE (wnd); return 0; }
case _TX_WM_CREATEWND: {$ _txCanvas_OnCREATEWND (wnd, wpar, lpar); return 0; }
case _TX_WM_DESTROYWND: {$ _txCanvas_OnDESTROYWND (wnd, wpar, lpar); return 0; }
case WM_NULL: {$ return 0; }
default: break; //-V2522
}
if (msg == WM_SYSCOMMAND) switch (wpar)
{
case _TX_IDM_ABOUT: {$ _txCanvas_OnCmdABOUT (wnd, wpar); return 0; }
case _TX_IDM_CONSOLE: {$ _txCanvas_OnCmdCONSOLE (wnd, wpar); return 0; }
default: break; //-V2522
}
$ return DefWindowProc (wnd, msg, wpar, lpar);
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCREATE (HWND wnd)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ _txCanvas_BackBuf[0] = _txBuffer_Create (wnd, NULL, NULL, &_txCanvas_Pixels); assert (_txCanvas_BackBuf[0]);
$ _txCanvas_BackBuf[1] = _txBuffer_Create (wnd, NULL, NULL, NULL); assert (_txCanvas_BackBuf[1]);
$ if (!SetTimer (wnd, _txCanvas_RefreshTimer, _txWindowUpdateInterval, NULL)) _txCanvas_RefreshTimer = 0;
$ assert (_txCanvas_RefreshTimer);
$ _txCanvas_UserDCs = new ::std::vector <HDC>;
$ _txCanvas_Window = wnd;
$ txSetDefaults();
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnDESTROY (HWND wnd)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
// Инициируем остановку цикла сообщений
$ PostQuitMessage (_txRunning? WM_DESTROY : EXIT_SUCCESS);
$ if (!_txCanvas_Window) return false;
// Indicate that we are about to manually terminate
$ _txExit = true;
// Lock GDI resources
$ bool locked = false;
$ _txWaitFor ((locked = txLock (false), locked), _TX_TIMEOUT);
$ if (!locked) TX_DEBUG_ERROR ("Cannot lock GDI to free resources");
// Освобождаем пользовательские ресурсы
$ if (_txCanvas_UserDCs && !_txCanvas_UserDCs->empty())
{
$ txNotifyIcon (NIIF_ERROR, NULL, "Вы забыли освободить %d HDC.", (int) _txCanvas_UserDCs->size()); //-V202
$ Sleep (_TX_TIMEOUT);
$ for (size_t i = 0; i < _txCanvas_UserDCs->size(); i++) _txBuffer_Delete (&_txCanvas_UserDCs->at (i));
$ _txCanvas_UserDCs->clear();
}
// Освобождаем ресурсы, связанные с окном
$ if (_txCanvas_RefreshTimer) KillTimer (wnd, _txCanvas_RefreshTimer) asserted;
$ if (_txCanvas_BackBuf[1]) _txBuffer_Delete (&_txCanvas_BackBuf[1]) asserted;
$ if (_txCanvas_BackBuf[0]) _txBuffer_Delete (&_txCanvas_BackBuf[0]) asserted;
$ _txCanvas_Pixels = NULL;
$ txUnlock();
// Indicate that we are destroyed
$ _txCanvas_Window = NULL;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCLOSE (HWND wnd) //-V2009 //-V2558
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ if (!_txCanvas_OK()) return false;
$ if (_txMain && _txRunning &&
txMessageBox ("Функция main() не завершена. Программа все еще работает. Прервать аварийно?\n\n"
"Лучше подождать, когда main() завершится - это отображается в заголовке окна.",
txGetModuleFileName (false), MB_YESNOCANCEL | MB_ICONSTOP) != IDYES) return false;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnTIMER (HWND wnd, WPARAM)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ if (_txCanvas_RefreshLock > 0 || !_txRunning) return false;
$ InvalidateRect (wnd, NULL, false) asserted;
$ UpdateWindow (wnd) asserted;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnPAINT (HWND wnd)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ if (!_txCanvas_OK()) return false;
$ bool forceRedraw = GetAsyncKeyState (VK_MENU) && GetAsyncKeyState (VK_CONTROL) &&
GetAsyncKeyState (VK_SHIFT) && GetAsyncKeyState (VK_SNAPSHOT);
$ PAINTSTRUCT ps = {};
$ HDC wndDc = BeginPaint (wnd, &ps);
$ if (!wndDc) return false;
$ HDC dc0 = _txCanvas_BackBuf[0],
dc1 = _txCanvas_BackBuf[1];
$ RECT r = {};
$ GetClientRect (wnd, &r) asserted;
$ POINT wndSize = { r.right - r.left, r.bottom - r.top };
$ POINT dcSize = txGetExtent (dc1);
$ if ((_txCanvas_RefreshLock <= 0 || forceRedraw) &&
txLock (false))
{
$ Win32::BitBlt (dc1, 0, 0, dcSize.x, dcSize.y, dc0, 0, 0, SRCCOPY);
$ if (_txConsole >= 0)
{$ _txConsole_Draw (dc1); }
$ txUnlock();
}
// Magic 100500 value is used to completely block screen refresh.
// Since no value can be 100500 or above, this condition is always true and the refresh cannot be blocked IRL.
// Do not use 100501 because it may lead to errors on some compilers and possible may crash the compilers
// themselves.
// Yes guys, with all your software installed. :(
$ if (_txCanvas_RefreshLock != 100500)
{
if (_txSwapBuffers)
{
$ _txSwapBuffers (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, dcSize.x, dcSize.y, SRCCOPY);
}
else if (dcSize.x == wndSize.x && dcSize.y == wndSize.y)
{
$ Win32::BitBlt (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, SRCCOPY);
}
else
{
$ Win32::SetStretchBltMode (wndDc, HALFTONE);
$ Win32::StretchBlt (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, dcSize.x, dcSize.y, SRCCOPY);
}
}
$ EndPaint (wnd, &ps) asserted;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCHAR (HWND, WPARAM ch, LPARAM info)
{
$8 INPUT_RECORD evt[2] = {};
$ evt[0].EventType = KEY_EVENT;
$ evt[0].Event.KeyEvent.bKeyDown = true;
$ evt[0].Event.KeyEvent.wRepeatCount = 1;
$ evt[0].Event.KeyEvent.uChar.AsciiChar = (char) (ch);
$ evt[0].Event.KeyEvent.wVirtualScanCode = (WORD) (info >> 16);
$ evt[0].Event.KeyEvent.wVirtualKeyCode = (WORD) MapVirtualKey ((WORD) (info >> 16), 3); // 3 == MAPVK_VSC_TO_VK_EX
$ evt[0].Event.KeyEvent.dwControlKeyState = 0;
$ evt[1] = evt[0];
$ evt[1].Event.KeyEvent.bKeyDown = false;
$ DWORD written = 0;
$ WriteConsoleInput (GetStdHandle (STD_INPUT_HANDLE), evt, 2, &written);
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnKEY (HWND, WPARAM vk, LPARAM info, bool down)
{
$8 INPUT_RECORD evt = {};
$ evt.EventType = KEY_EVENT;
$ evt.Event.KeyEvent.bKeyDown = down;
$ evt.Event.KeyEvent.wRepeatCount = 1;
$ evt.Event.KeyEvent.uChar.AsciiChar = (char) MapVirtualKey ((WORD) vk, 2); // 2 == MAPVK_VK_TO_CHAR
$ evt.Event.KeyEvent.wVirtualScanCode = (WORD) (info >> 16);
$ evt.Event.KeyEvent.wVirtualKeyCode = (WORD) vk;
$ evt.Event.KeyEvent.dwControlKeyState = (DWORD) (info & (1 << (24-1)))? ENHANCED_KEY : 0;
$ if (evt.Event.KeyEvent.uChar.AsciiChar) return false; // Let TranslateMessage() and WM_CHAR do the job
$ DWORD written = 0;
$ WriteConsoleInput (GetStdHandle (STD_INPUT_HANDLE), &evt, 1, &written);
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnMOUSEMOVE (HWND wnd, WPARAM buttons, LPARAM coords)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ if (!_txCanvas_OK()) return false;
$ if (_txMousePos.x == -1 && _txMousePos.y == -1)
{
$ TRACKMOUSEEVENT track = { sizeof (track), TME_HOVER | TME_LEAVE, wnd, HOVER_DEFAULT };
$ TrackMouseEvent (&track);
}
$ _txMousePos.x = LOWORD (coords);
$ _txMousePos.y = HIWORD (coords);
$ _txMouseButtons = (unsigned) buttons; //-V202
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnMOUSELEAVE (HWND)
{
$8 _txMousePos.x = -1;
$ _txMousePos.y = -1;
$ _txMouseButtons = 0;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCREATEWND (HWND, WPARAM, LPARAM lpar)
{
$8 if (_TX_ARGUMENT_FAILED (lpar)) return false;
$ const CREATESTRUCT* create = (CREATESTRUCT*) lpar;
$ HWND wnd = CreateWindowEx (create->dwExStyle, create->lpszClass, create->lpszName, create->style,
create->x, create->y, create->cx, create->cy,
create->hwndParent, create->hMenu, NULL, create->lpCreateParams);
$ *(HWND*) create->hInstance = wnd;
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnDESTROYWND (HWND, WPARAM, LPARAM lpar)
{
$8 if (_TX_ARGUMENT_FAILED (lpar)) return false;
$ DestroyWindow ((HWND) lpar);
$ return false;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCmdCONSOLE (HWND wnd, WPARAM cmd)
{
$8 if (_TX_ARGUMENT_FAILED (wnd)) return false;
$ HWND console = Win32::GetConsoleWindow();
$ if (!console) return false;
$ bool visible = !!IsWindowVisible (console);
$ ShowWindow (console, visible? SW_HIDE : SW_RESTORE);
$ visible = !!IsWindowVisible (console);
$ CheckMenuItem (GetSystemMenu (wnd, false), (int) cmd, visible? MF_CHECKED : MF_UNCHECKED); //-V202
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCanvas_OnCmdABOUT (HWND, WPARAM)
{
$8 //{ Overriding the missing names, if the set is uncomplete
#if defined (__MODULE)
#define ABOUT_NAME_ __MODULE
#else
#define ABOUT_NAME_ "TXLib"
#endif
#if defined (__MODULE) || defined (__VERSION) || defined (__DESCRIPTION) || defined (__AUTHOR)
#ifndef __MODULE
#define __MODULE "TXLib" "\n" "#define __MODULE to set the name.\n"
#endif
#ifndef __VERSION
#define __VERSION "(0.000000000)." "\n" "#define __VERSION to set the string value.\n"
#endif
#ifndef __DESCRIPTION
#define __DESCRIPTION "(Да, мне лень задать описание)." "\n" "#define __DESCRIPTION to override project role.\n"
#endif
#ifndef __AUTHOR
#define __AUTHOR "(Непонятно кто)." "\n" "#define __AUTHOR to override this name."
#endif
#endif
//}
$ static char text[_TX_BUFSIZE] = "";
$ _tx_snprintf_s (text, sizeof (text) - 1,
"Application:\n\n"
#if defined (__MODULE) || defined (__VERSION) || defined (__DESCRIPTION) || defined (__AUTHOR)
__MODULE " version " __VERSION "\n" __DESCRIPTION "\n" "Copyright (c) " __AUTHOR "\n"
#else
"Здесь могла бы быть Ваша реклама :)\n"
"#define __MODULE to \"your program name\" before including TXLib.h to use this billboard...\n"
#endif
"\n" "%s", _txAppInfo());
$ txMessageBox (text, "About " ABOUT_NAME_, MB_ICONINFORMATION);
// And a bit of HTTP-code in C++ function:
goto http;
http://sizeof.livejournal.com
$ return true;
#undef ABOUT_NAME_
}
#endif // TX_COMPILED
//! @}
//}
//=================================================================================================================
//=================================================================================================================
//{ Console-support functions (_txConsole...)
//! @name Функции консольного окна (_txConsole...)
//=================================================================================================================
//! @{
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
HWND _txConsole_Attach()
{
$1 HWND console = Win32::GetConsoleWindow();
$ if (!console)
{
$ bool minimizeConsole = ((TX_CONSOLE_MODE) == SW_HIDE && !_txIsConsoleSubsystem());
$ Win32::TEB* teb = (Win32::TEB*) NtCurrentTeb();
$ assert (teb);
$ assert (teb->ProcessEnvironmentBlock);
$ Win32::RTL_USER_PROCESS_PARAMETERS* params = teb->ProcessEnvironmentBlock->ProcessParameters;
$ assert (params);
$ if (minimizeConsole) // The fact that ShowWindow parameter of the program's console is taken from calling
// process' STARTUPINFO, was researched from Windows XP sources. See SetUpConsoleInfo()
// in windows\core\ntcon\client\dllinit.c. No one can miss stealing Windows sources. :(
// Thank you Matt Pietrek, the author of "Undocumented Windows". Use the Source, Luke!..
{
$ params->dwFlags |= STARTF_USESHOWWINDOW;
$ params->wShowWindow = SW_MINIMIZE;
}
$ AllocConsole();
$ console = Win32::GetConsoleWindow();
}
$ if (!console) return NULL;
$ txSetLocale(); // Устанавливаем русскую кодовую страницу для консоли Windows
$ _txConsole_SetUnicodeFont(); // Впечатлительным лучше сюда не смотреть.
$ if (!_txIsConsoleSubsystem())
{$ txReopenStdio(); } // Переоткрываем потоки ввода-вывода, если subsystem != console
$ return console;
}
//-----------------------------------------------------------------------------------------------------------------
int txSetLocale (int codepage /*= _TX_CODEPAGE*/,
const char locale[] /*= _TX_LOCALE*/, const wchar_t wLocale[] /*= _TX_WLOCALE*/)
{
$1 int oldPage = GetConsoleOutputCP();
// Устанавливаем нужную кодовую страницу для консоли Windows
$ if (codepage)
{
$ SetConsoleCP (codepage);
$ SetConsoleOutputCP (codepage);
}
// Устанавливаем нужную кодовую страницу для стандартной библиотеки, иначе не будут работать Unicode-версии
// функций (wprintf, ...). Если компилите с помощью gcc и собираетесь использовать L"unicode-строки" с определенным
// языком, укажите опции в командной строке компилятора g++: -finput-charset=NNNN -fexec-charset=NNNN, где NNNN -
// обозначение кодовой страницы (например, для русского языка - CP1251).
$ if (locale)
{
$ setlocale (LC_ALL, locale);
$ setlocale (LC_NUMERIC, "C"); // Return to decimal point (3.14) instead of comma (3,14) in floating numbers
}
#ifndef __CYGWIN__
$ const bool wine = !!Win32::wine_get_version; // Linux::Wine v1.2.2+ compatibility.
$ if (wLocale && !wine)
{
$ _wsetlocale (LC_ALL, wLocale);
$ _wsetlocale (LC_NUMERIC, L"C"); // L"C" (see above)
}
#endif
(void) wLocale;
$ return oldPage;
}
//-----------------------------------------------------------------------------------------------------------------
void txReopenStdio()
{
$1 // Переоткрываем заново <s>Америку); break; }
9228 if (canvas && !SendMessageTimeout (canvas, WM_NULL, 0,0, SMTO_BLOCK | SMTO_ABORTIFHUNG,
_TX_TIMEOUT, NULL))
9229 {$ _txTrace (__FILE__, __LINE__, NULL,
"WARNING: Программа не отвечает");
break; }
9231 if (!wine && !(i % 100500))
9232 {$ fprintf (stderr,
"\r" "[Так нажмите же какую-нибудь клавишу...] \b\b"); }
9235 if (istty0) {$
while (!wine && _kbhit()) ch = _getch(); }
9237 $ _txSetWindowText (wnd, NULL);
9239 $ fprintf (stderr,
"\n");
9241 if (ch == 3 ) {$
raise (SIGABRT); }
9243 $ SetConsoleOutputCP (oldCP);
9253 $4 HANDLE con = GetStdHandle (STD_INPUT_HANDLE);
9257 $
if (GetConsoleMode (con, &nChars) == 0 &&
9258 PeekNamedPipe (con, NULL, 0, NULL, &nChars, NULL))
9260 $ ch = (nChars)? fgetc (stdin) : EOF;
9268 #if defined (_MSC_VER) && (_MSC_VER < 1700)
9270 else if (fseek (stdin, 1, SEEK_CUR) != EOF)
9272 $ (void) fseek (stdin, -1, SEEK_CUR);
9273 $ ch = fgetc (stdin);
9278 if (ch == 3 ) {$
raise (SIGABRT); }
9285 bool _txIsTTY (
int fd)
9287 $4
return GetFileType ((HANDLE)_get_osfhandle (fd)) == FILE_TYPE_CHAR;
9292 int _txSetWindowText (HWND wnd,
const char* textRus,
const char* textEng ,
9293 int checkOfs ,
const wchar_t checkLetters[2] )
9297 static LRESULT getWindowText (HWND window,
wchar_t text[],
size_t size)
9299 $3 memset (text, 0, size *
sizeof (*text));
9301 $
return SendMessageTimeoutW (window, WM_GETTEXT, (WPARAM) size, (LPARAM) text, SMTO_BLOCK | SMTO_ABORTIFHUNG,
_TX_TIMEOUT, NULL);
9304 static LRESULT setWindowText (HWND window,
wchar_t text[])
9306 $1
return SendMessageTimeoutW (window, WM_SETTEXT, 0, (LPARAM) text, SMTO_BLOCK | SMTO_ABORTIFHUNG,
_TX_TIMEOUT, NULL);
9310 $1
static wchar_t _tx_thread title [
_TX_BUFSIZE+15] = L
"TXLib";
9311 $
static wchar_t _tx_thread oldTitle [
_TX_BUFSIZE+15] = L
"TXLib";
9315 $ tools::setWindowText (wnd, oldTitle);
9319 $ tools::getWindowText (wnd, title,
_TX_BUFSIZE-1);
9321 $ memcpy (oldTitle, title,
sizeof (oldTitle));
9327 $ tools::setWindowText (wnd, title);
9328 $ tools::getWindowText (wnd, title,
_TX_BUFSIZE-1);
9329 if (checkLetters && len <= (
int)
_TX_BUFSIZE-1-2 && title [len + checkOfs] == checkLetters[0]) {$
return 0; }
9330 if (!checkLetters) {$
return -2; }
9337 $ tools::setWindowText (wnd, title);
9338 $ tools::getWindowText (wnd, title,
_TX_BUFSIZE-1);
9339 if (checkLetters && len <= (
int)
_TX_BUFSIZE-1-2 && title [len + checkOfs] == checkLetters[1]) {$
return 1; }
9340 if (!checkLetters) {$
return -2; }
9348 int _txIsParentWaitable (DWORD* parentPID )
9350 $4 PROCESSENTRY32* info = _txFindProcess();
9351 $
if (!info)
return 0;
9353 $ info = _txFindProcess (info->th32ParentProcessID);
9354 $
if (!info)
return 0;
9356 $
char parent [MAX_PATH] =
"";
9357 $ strncpy_s (parent,
sizeof (parent), info->szExeFile, sizeof (parent) - 1);
9358 $
if (parentPID) *parentPID = info->th32ProcessID;
9360 $ info = _txFindProcess (info->th32ParentProcessID);
9365 $
for (
char* p = strtok_s (list,
", ", &ctx); p; p = strtok_s (NULL,
", ", &ctx))
9367 $
char* gp = strchr (p,
':');
9373 $
if (_stricmp (p, parent) != 0) {
continue; }
9375 $
if (info)
if (_stricmp (gp, info->szExeFile) == 0)
9376 {$
return islower ((
unsigned char) *gp)? +1 : -1; }
9380 $
if (_stricmp (p, parent) == 0)
9381 {$
return islower ((
unsigned char) *p)? +1 : -1; }
9390 void _txWatchdogTerminator (
void* timeout)
9392 $3
if (_TX_ARGUMENT_FAILED (timeout))
return;
9394 $ Sleep (*(
int*) timeout);
9396 $ OutputDebugString (
"\n");
9398 _TX_VERSION, __func__, *(
int*) timeout, ((__func__[8] ==
'd')?
"Bark, bark" :
"Meow, meow"));
9400 $
if (_txIsParentWaitable (&parent))
9403 _TX_VERSION, __func__, (
unsigned long) parent);
9405 $ _txKillProcess (parent);
9407 $ HWND console = GetConsoleWindow();
9408 $ PostMessage (console, WM_KEYDOWN, VK_RETURN, 0x001C0001);
9409 $ PostMessage (console, WM_KEYUP, VK_RETURN, 0xC01C0001);
9412 txOutputDebugPrintf (
"%s - WARNING: %s(): Calling Win32::TerminateProcess (EXIT_FAILURE)\n", _TX_VERSION, __func__);
9413 $ Win32::TerminateProcess (GetCurrentProcess(), EXIT_FAILURE);
9429 int _txTaskKill (
const char i[] ,
9430 const char doYouWantToFindSomethingInTheCommandLineIDidSomethingForYouToFindSomethingInTheCommandLineMaybeYouWillFindSomeInterestingInTheCommandLineSoIDidSomethingForYouInTheCommandLine[] ,
9436 #define cmdLineSubstr doYouWantToFindSomethingInTheCommandLineIDidSomethingForYouToFindSomethingInTheCommandLineMaybeYouWillFindSomeInterestingInTheCommandLineSoIDidSomethingForYouInTheCommandLine
9439 $3
if (_TX_ARGUMENT_FAILED ((name || cmdLineSubstr || pid) &&
"Вот такие тут интересные имена встречаются..."))
return false;
9442 if (cmdLineSubstr) {$ MultiByteToWideChar (
_TX_CODEPAGE, 0, cmdLineSubstr, -1, cmdLineSubstrW,
sizearr (cmdLineSubstrW)); }
9444 $ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
9445 $ assert (sshot);
if (!sshot)
return 0;
9449 $ PROCESSENTRY32 info = {
sizeof (info) };
9450 $
for (
bool ok = !!Process32First (sshot, &info); ok; ok = !!Process32Next (sshot, &info))
9454 if (!kill && pid && info.th32ParentProcessID == pid) {$ kill =
true; }
9456 if (!kill && name && _stricmp (info.szExeFile, name) == 0) {$ kill =
true; }
9461 if (!_txGetCommandLine (cmdLineW,
sizearr (cmdLineW), info.th32ProcessID)) {
continue; }
9463 if (*cmdLineW && stristrw (cmdLineW, cmdLineSubstrW)) {$ kill =
true; }
9468 $
if (_txKillProcess (info.th32ProcessID))
9473 $ CloseHandle (sshot);
9484 bool _txKillProcess (DWORD pid)
9486 $3
if (_TX_ARGUMENT_FAILED (pid))
return false;
9488 $ HANDLE token = INVALID_HANDLE_VALUE;
9489 $ OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)
asserted;
9492 $ LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &luid)
asserted;
9494 $ TOKEN_PRIVILEGES priv = { 1, {{{ luid.LowPart, luid.HighPart}, SE_PRIVILEGE_ENABLED }}};
9495 $ TOKEN_PRIVILEGES old = {};
9498 $ AdjustTokenPrivileges (token,
false, &priv,
sizeof (priv), &old, &oldSz)
asserted;
9500 $ HANDLE proc = OpenProcess (PROCESS_ALL_ACCESS, 0, pid);
9501 $
if (!proc)
return false;
9503 $
bool ok = !!Win32::TerminateProcess (proc, 0);
9504 $ CloseHandle (proc);
9511 PROCESSENTRY32* _txFindProcess (
unsigned pid )
9513 $4
static PROCESSENTRY32 info = {
sizeof (info) };
9514 $
if (!pid)
return &info;
9516 $ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
9517 $ assert (sshot);
if (!sshot)
return NULL;
9519 $
for (
bool ok = !!Process32First (sshot, &info); ok; ok = !!Process32Next (sshot, &info))
9520 if (info.th32ProcessID == pid)
break;
9522 $ CloseHandle (sshot);
9529 bool _txGetCommandLine (
wchar_t cmdLine[],
size_t szCmdLine,
unsigned pid )
9531 $6
if (_TX_ARGUMENT_FAILED (cmdLine))
return false;
9532 $
if (_TX_ARGUMENT_FAILED (szCmdLine >= 2))
return false;
9534 $
if (pid == (
unsigned) _getpid())
9536 $ wcsncpy_s (cmdLine, szCmdLine, GetCommandLineW(), szCmdLine-1);
9540 $ HANDLE proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
false, pid);
9541 if (!proc) {$
return false; }
9543 $ Win32::PROCESS_BASIC_INFORMATION pbi = {};
9544 $
bool ok = (Win32::NtQueryInformationProcess (proc, 0 , &pbi,
sizeof (pbi), NULL) == 0);
9548 $ Win32::PEB peb = {};
9549 if (ok && pbi.PebBaseAddress) {$ ok &= !!ReadProcessMemory (proc, pbi.PebBaseAddress, &peb, sizeof (peb), NULL); }
9551 $ Win32::RTL_USER_PROCESS_PARAMETERS params = {};
9552 if (ok && peb.ProcessParameters) {$ ok &= !!ReadProcessMemory (proc, peb.ProcessParameters, ¶ms, sizeof (params), NULL); }
9555 if (ok && params.CommandLine.Buffer) {$ ok &= !!ReadProcessMemory (proc, params.CommandLine.Buffer, cmdLine,
9556 MIN (params.CommandLine.Length + 2, (
int) (szCmdLine * sizeof (*cmdLine)) - 2),
9565 #define RVA_(type, module, addr) ( (type) ((uintptr_t) (module) + (uintptr_t) (addr)) )
9567 IMAGE_NT_HEADERS* _txGetNtHeaders (HMODULE module )
9571 $ IMAGE_DOS_HEADER* dosHdr = RVA_ (IMAGE_DOS_HEADER*, module, 0);
9572 $ IMAGE_NT_HEADERS* ntHdr = RVA_ (IMAGE_NT_HEADERS*, module, dosHdr->e_lfanew);
9574 $
return (dosHdr->e_magic == IMAGE_DOS_SIGNATURE &&
9575 ntHdr->Signature == IMAGE_NT_SIGNATURE)? ntHdr : NULL;
9582 uintptr_t _txSetProcAddress (
const char funcName[], uintptr_t newFunc,
const char dllName[] ,
int useHotPatching ,
9583 HMODULE module ,
bool debug )
9585 $4
if (debug)
txOutputDebugPrintf (
"_txSetProcAddress (%s, 0x%p, %s, 0x%p):\n", funcName, (
void*) newFunc, dllName, (
void*) module);
9587 $
if (_TX_ARGUMENT_FAILED (funcName))
return 0;
9588 $
if (_TX_ARGUMENT_FAILED (newFunc))
return 0;
9590 $
if (!module) module = GetModuleHandle (NULL);
9591 $
if (!module)
return 0;
9593 $ HMODULE dll = (dllName)? GetModuleHandle (dllName) : NULL;
9594 $ PROC oldFunc = (dll)? GetProcAddress (dll, funcName) : NULL;
9596 $
if (useHotPatching && oldFunc)
9598 $
const size_t jmpSz = 1 +
sizeof (DWORD);
9600 $ DWORD oldRights = 0;
9601 $
if (!VirtualProtect ((
void*)(uintptr_t) oldFunc, jmpSz, PAGE_EXECUTE_READWRITE, &oldRights))
return 0;
9606 $ *(BYTE*) ((
char*)(uintptr_t) oldFunc + 0) = 0xE9;
9607 $ *(DWORD*) ((
char*)(uintptr_t) oldFunc + 1) = ((
char*)(uintptr_t) newFunc - (
char*)(uintptr_t) oldFunc - jmpSz) & 0xFFFFFFFF;
9609 $ FlushInstructionCache (GetCurrentProcess(), (
void*)(uintptr_t) oldFunc, jmpSz);
9611 $ VirtualProtect ((
void*)(uintptr_t) oldFunc, jmpSz, oldRights, &oldRights);
9613 $
return (uintptr_t) oldFunc;
9619 $ IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders (module);
9620 if (!ntHdr || (ntHdr ->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)) {$
return 0; }
9622 $ DWORD impOffset = ntHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
9623 $ IMAGE_IMPORT_DESCRIPTOR* desc = RVA_ (IMAGE_IMPORT_DESCRIPTOR*, module, impOffset);
9625 $
if (desc == (IMAGE_IMPORT_DESCRIPTOR*) ntHdr)
return 0;
9627 $ IMAGE_THUNK_DATA* thunk0 = NULL, * thunk1 = NULL;
9628 $
char* impDll = NULL;
9629 $
char* impName = NULL;
9630 $
void** impPtr = NULL;
9631 $
bool found =
false;
9633 for (; desc->Name; desc++)
9635 $ impDll = RVA_ (
char*, module, desc->Name);
9636 $
if (dllName && _stricmp (impDll, dllName) != 0)
continue;
9638 $
for (thunk0 = RVA_ (IMAGE_THUNK_DATA*, module, desc->OriginalFirstThunk),
9639 thunk1 = RVA_ (IMAGE_THUNK_DATA*, module, desc->FirstThunk);
9641 thunk0 && thunk1 && thunk1->u1.Function;
9646 impName = (
char*) RVA_ (IMAGE_IMPORT_BY_NAME*, module, thunk0->u1.AddressOfData) -> Name;
9647 impPtr = (
void**)(uintptr_t) &thunk1->u1.Function;
9649 if (IsBadReadPtr (impName,
sizeof (impName))) impName = NULL;
9653 if ((oldFunc && (uintptr_t) oldFunc == (uintptr_t) *impPtr) ||
9654 (impName && _stricmp (funcName, impName) == 0))
9665 funcName, (
void*) newFunc, dllName, (
void*) module, (found?
"FOUND" :
"NOT found"));
9666 $
if (!found)
return 0;
9668 $ DWORD rights = PAGE_READWRITE;
9669 $
if (!VirtualProtect (impPtr,
sizeof (*impPtr), rights, &rights))
return 0;
9671 $ *(uintptr_t*) impPtr = newFunc;
9673 $ VirtualProtect (impPtr,
sizeof (*impPtr), rights, &rights);
9675 $
return (uintptr_t) oldFunc;
9684 $4 MODULEENTRY32 mod = {
sizeof (mod) };
9686 $ HANDLE sshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
9687 $ assert (sshot);
if (!sshot)
return false;
9689 $
bool inDll =
false;
9691 $
for (
bool ok = !!Module32First (sshot, &mod); ok; ok = !!Module32Next (sshot, &mod))
9693 $
if (!mod.modBaseAddr)
continue;
9695 $ IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders ((HMODULE) mod.modBaseAddr);
9697 $ inDll = ntHdr && ((ntHdr->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0);
9699 $
if (
In (std::nomeow, (BYTE*)(uintptr_t)_txInDll, mod.modBaseAddr, mod.modBaseAddr + mod.modBaseSize))
9703 $ CloseHandle (sshot);
9709 bool _txIsConsoleSubsystem()
9711 $4 IMAGE_NT_HEADERS* ntHdr = _txGetNtHeaders();
9714 ntHdr ->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC &&
9716 (ntHdr ->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI ||
9717 ntHdr ->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_POSIX_CUI);
9722 bool _txIsBadReadPtr (
const void* address)
9724 MEMORY_BASIC_INFORMATION mbi = {};
9725 if (!VirtualQuery (address, &mbi,
sizeof (mbi)))
return true;
9727 if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS))
return true;
9729 DWORD readRights = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
9731 return !(mbi.Protect & readRights);
9736 void _txActivateWindow (HWND wnd,
unsigned mode)
9738 $1 EnableWindow (wnd,
true);
9742 $ ShowWindow (wnd, SW_MINIMIZE);
9743 $ ShowWindow (wnd, SW_RESTORE);
9748 $
int focus = GetWindowThreadProcessId (GetForegroundWindow(), 0);
9750 $ AttachThreadInput (GetCurrentThreadId(), focus,
true);
9751 $ SetForegroundWindow (wnd);
9752 $ AttachThreadInput (GetCurrentThreadId(), focus,
false);
9757 $ SetWindowPos (wnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
9762 $ SetWindowPos (wnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_ASYNCWINDOWPOS);
9767 $ UpdateWindow (wnd);
9787 unsigned WINAPI _txCanvas_ThreadProc (
void* data)
9789 #define SetClassLong_ SetClassLongPtr
9790 #define GCL_HICON_ GCLP_HICON
9791 #define GCL_HICONSM_ GCLP_HICONSM
9792 #define GCL_HCURSOR_ GCLP_HCURSOR
9794 $8 _txCanvas_ThreadId = GetCurrentThreadId();
9796 $
if (_TX_ARGUMENT_FAILED (data))
return false;
9799 $ _TX_CALL (Win32::SetThreadStackGuarantee, (&stackSize));
9801 $ HWND wnd = _txCanvas_CreateWindow ((SIZE*) data);
9804 $ HICON icon32 = LoadIcon (NULL,
"_TX_ICON");
9805 $ HICON icon16 = LoadIcon (NULL,
"_TX_ICONSM");
9806 $ HCURSOR cursor = LoadCursor (NULL,
"_TX_CURSOR");
9807 $ HMENU menu = LoadMenu (NULL,
"_TX_MENU");
9808 $ HACCEL accel = LoadAccelerators (NULL,
"_TX_ACCELERATORS");
9810 $ SetClassLong_ (wnd, GCL_HICON_, (LONG_PTR) (icon32? icon32 : _txCreateTXIcon (32)));
9811 $ SetClassLong_ (wnd, GCL_HICONSM_, (LONG_PTR) (icon16? icon16 : _txCreateTXIcon (16)));
9812 $ SetClassLong_ (wnd, GCL_HCURSOR_, (LONG_PTR) (cursor? cursor : LoadCursor (NULL, IDC_ARROW)));
9814 if (menu) {$ SetMenu (wnd, menu); DrawMenuBar (wnd); }
9816 $ Win32::GdiSetBatchLimit (1);
9818 _TX_ON_DEBUG (OutputDebugString (_TX_VERSION
" - STARTED: " _TX_MODULE "\n"));
9820 $ _txActivateWindow (wnd, 0x10);
9822 $ ShowWindow (wnd, SW_SHOW);
9823 $ UpdateWindow (wnd);
9825 $ _txRunning =
true;
9828 $
while (GetMessage (&msg, NULL, 0, 0))
9830 if (!msg.hwnd) {$
continue; }
9832 if (accel && TranslateAccelerator (wnd, accel, &msg)) {$
continue; }
9834 $ TranslateMessage (&msg);
9835 $ DispatchMessage (&msg);
9840 $
if (icon16) DestroyIcon (icon16);
9841 $
if (icon32) DestroyIcon (icon32);
9843 $ LeaveCriticalSection (&_txCanvas_LockBackBuf);
9845 _TX_ON_DEBUG (OutputDebugString (_TX_VERSION
" - STOPPED: " _TX_MODULE "\n"));
9850 $
if (_txRunning && _txMain)
9853 $ ::exit ((
int) msg.wParam);
9856 $ _txCanvas_ThreadId = 0;
9867 HWND _txCanvas_CreateWindow (
const SIZE* sizePtr)
9869 $8
if (_TX_ARGUMENT_FAILED (sizePtr))
return NULL;
9871 $
bool centered =
false;
9872 if (sizePtr->cx < 0 && sizePtr->cy < 0) {$ centered =
true; }
9874 $ SIZE screen = { GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN) };
9875 $ RECT rect = { 0, 0, abs (sizePtr->cx), abs (sizePtr->cy) }; AdjustWindowRect (&rect,
_txWindowStyle,
false);
9876 $ SIZE size = { rect.right - rect.left, rect.bottom - rect.top };
9879 $ HWND console = _TX_CALL (Win32::GetConsoleWindow, ());
9880 if (console) {$ GetWindowRect (console, &conPos); }
9882 $
const char* wndClass = txRegisterClass (
"MAIN", _txCanvas_WndProc, CS_HREDRAW | CS_VREDRAW | CS_OWNDC, BLACK_BRUSH, 0);
9883 $
if (!wndClass)
return (HWND) NULL;
9886 (centered)? screen.cx/2 - size.cx/2 : (console)? conPos.left : CW_USEDEFAULT,
9887 (centered)? screen.cy/2 - size.cy/2 : (console)? conPos.top : CW_USEDEFAULT,
9888 size.cx, size.cy, NULL, NULL, NULL, NULL);
9890 {$
return TX_DEBUG_ERROR (
"Cannot create canvas: CreateWindowEx() failed"), (HWND) NULL; }
9892 $ HMENU menu = GetSystemMenu (
txWindow(),
false);
9895 $ AppendMenu (menu, MF_SEPARATOR, 0, NULL)
asserted;
9896 $ AppendMenu (menu, MF_STRING, _TX_IDM_CONSOLE,
"Show &Console")
asserted;
9897 $ AppendMenu (menu, MF_STRING, _TX_IDM_ABOUT, "&About...")
asserted;
9904 const
char* txRegisterClass (const
char classId[], WNDPROC wndProc,
unsigned style,
int backBrush,
int wndExtra)
9906 $8 assert (classId);
9910 $ _tx_snprintf_s (name,
sizeof (name) - 1,
"/*---[TXLib]-[%s]------------ "
9911 _TX_VERSION
" " __FILE__
" WndClass %08lX "
9912 "-------------[%s]-[TXLib]---*/",
9913 classId, (
unsigned long) GetTickCount(), classId);
9914 $ WNDCLASS wc = {
sizeof (wc) };
9916 $ wc.lpszClassName = name;
9917 $ wc.lpfnWndProc = wndProc;
9919 $ wc.cbWndExtra = (wndExtra + 1) * (
int)
sizeof (long);
9921 $ wc.hCursor = LoadCursor (NULL, IDC_ARROW);
9922 $ wc.hbrBackground = (HBRUSH) Win32::GetStockObject (backBrush);
9924 $ ATOM atom = RegisterClass (&wc);
9925 if (!atom) {$
TX_DEBUG_ERROR (
"RegisterClass (\"%s\") failed", name);
return 0; }
9927 $
return (
const char*)(uintptr_t) atom;
9932 int _txCanvas_SetRefreshLock (
int count)
9934 $8
int oldCount = _txCanvas_RefreshLock;
9936 $ _txCanvas_RefreshLock = count;
9940 $
if ((_txCanvas_RefreshLock <= 0 || oldCount <= 0) && wnd)
9941 {$ RedrawWindow (wnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_UPDATENOW); }
9948 HICON _txCreateTXIcon (
int size)
9950 $8
if (_TX_ARGUMENT_FAILED (size == 32 || size == 16))
return NULL;
9952 $
const unsigned char image32 [32*32+1] =
9953 "00000000000000000000000000000000""0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0""0F0000000000000000000000000000F0""0F0000000000000000000000000000F0"
9954 "0F0000000000000099999999999900F0""0F0000000000000090300333330900F0""0F0000000990000090000000000900F0""0F00000099990000900BB000000900F0"
9955 "0F0000039999000090B00090900900F0""0F0000009999000090B00999990900F0""0F00000009903799900BB090900900F0""0F000000009BB70090000010000900F0"
9956 "0F0000000B90000090000000000900F0""0F000000B0B0000099999999999900F0""0F00007B30B0000090000000000000F0""0F00007300B0000090000000000000F0"
9957 "0F00000000B3000090000000000000F0""0F0000000B0B000090000000000000F0""0F000000B303B00090000000000000F0""0F000003B000B00090000000000000F0"
9958 "0F00003B00003B0090000000000000F0""0F0000300000030090000000000000F0""0F0000000448888888888844000000F0""0F00004886E6E6E60E66E6EEEE4400F0"
9959 "0F4488866E0E60E00660E06E66EEE4F0""0F868806E06E06E666E66E00E06EE6F0""0F08606E66E0066000E006E66E00E6F0""0F8666E006600E00006600E006E00EF0"
9960 "0F000E066888888888888888606660F0""0F66EEE6EE000E00000E00086EEEE6F0""0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0""00000000000000000000000000000000";
9962 $
const unsigned char image16 [16*16+1] =
9963 "0000000000000000""0000000999999990""0009000900000090""0099900909973090""0059700909009390""0009799909973090""0099000900000090""0959330999999990"
9964 "0709500900000000""0095930900000000""0090393900000000""0790073900000000""0900000900000000""000EE6E6E6E6E000""0EE6E6E6E6E6EEE0""0000000000000000";
9966 $
const COLORREF pal[
'F'-
'0'+1] = { 0x000000, 0x002b2b, 0x555500, 0x005555, 0x808000, 0x008080, 0xaaaa00, 0x00aaaa, 0xd5d500, 0x00d5d5, 0,0,0,0,0,0,0,
9967 0xffff00, 0x00ffff, 0xffffaa, 0xaaffff, 0xd5d500, 0xffffff };
9969 $
const unsigned char* image = (size == 32)? image32 : image16;
9971 $ POINT sz = { size, size };
9972 $ HDC dcMask = _txBuffer_Create (
txWindow(), &sz); assert (dcMask);
9973 $ HDC dcColor = _txBuffer_Create (
txWindow(), &sz); assert (dcColor);
9975 $
for (
int i = 0; i < size*size; i++)
9977 assert (
In (std::nomeow, image[i],
'0',
'9') ||
9978 In (std::nomeow, image[i],
'A',
'F'));
9980 Win32::SetPixel (dcColor, i % size, i / size, pal [image[i] -
'0']);
9983 $ ICONINFO info = {
true, 0, 0, (HBITMAP) Win32::GetCurrentObject (dcMask, OBJ_BITMAP),
9984 (HBITMAP) Win32::GetCurrentObject (dcColor, OBJ_BITMAP) };
9986 $ HICON icon = CreateIconIndirect (&info);
9989 $ _txBuffer_Delete (&dcMask)
asserted;
9990 $ _txBuffer_Delete (&dcColor)
asserted;
9999 inline bool _txCanvas_OK()
10001 return _txCanvas_ThreadId &&
10002 _txCanvas_Window &&
10003 _txCanvas_BackBuf[0] &&
10004 _txCanvas_BackBuf[1] &&
10017 #ifndef TX_COMPILED
10019 LRESULT CALLBACK _txCanvas_WndProc (HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar)
10021 #if defined (_TX_ALLOW_TRACE)
10023 int inTX = _txLoc::Cur.inTX++;
10025 if (_txLoc::Cur.trace) _txTrace (__FILE__, __LINE__,
__TX_FUNCTION__,
"%*s" "0x%X <- 0x%04X (0x%08X, 0x%08lX)",
10026 2 * (_txLoc::Cur.inTX - 1),
"", wnd, msg, wpar, lpar);
10027 _txLoc::Cur.inTX = inTX;
10031 $8
if (msg == WM_KEYDOWN && wpar == VK_F12 &&
10032 GetKeyState (VK_SHIFT) && GetKeyState (VK_CONTROL) && GetKeyState (VK_MENU))
10034 $ _txCanvas_OnCmdABOUT (wnd, wpar);
10035 $
return DefWindowProc (wnd, msg, wpar, lpar);
10038 WNDPROC altWndProc = _txAltWndProc;
10041 $ LRESULT res = altWndProc (wnd, msg, wpar, lpar);
10042 $
if (res)
return res;
10045 static bool bkErased =
false;
10049 case WM_CREATE: {$ _txCanvas_OnCREATE (wnd);
return 0; }
10051 case WM_CLOSE: {$
if (_txCanvas_OnCLOSE (wnd))
break;
else return 0; }
10052 case WM_DESTROY: {$ _txCanvas_OnDESTROY (wnd);
return 0; }
10054 case WM_ERASEBKGND: {$
if (!bkErased) { bkErased =
true;
break; }
else return 1; }
10055 case WM_SIZE: {$ bkErased =
false;
break; }
10057 case WM_PAINT: {$ _txCanvas_OnPAINT (wnd);
return 0; }
10059 case WM_TIMER: {$ _txCanvas_OnTIMER (wnd, wpar);
return 0; }
10061 case WM_KEYUP: {$
if (_txCanvas_OnKEY (wnd, wpar, lpar,
false))
return 0;
else break; }
10062 case WM_KEYDOWN: {$
if (_txCanvas_OnKEY (wnd, wpar, lpar,
true))
return 0;
else break; }
10063 case WM_CHAR: {$
if (_txCanvas_OnCHAR (wnd, wpar, lpar))
return 0;
else break; }
10066 case WM_LBUTTONDOWN:
10068 case WM_RBUTTONDOWN:
10070 case WM_MBUTTONDOWN:
10071 case WM_MOUSEMOVE: {$ _txCanvas_OnMOUSEMOVE (wnd, wpar, lpar);
return 0; }
10073 case WM_MOUSELEAVE: {$ _txCanvas_OnMOUSELEAVE (wnd);
return 0; }
10075 case _TX_WM_CREATEWND: {$ _txCanvas_OnCREATEWND (wnd, wpar, lpar);
return 0; }
10076 case _TX_WM_DESTROYWND: {$ _txCanvas_OnDESTROYWND (wnd, wpar, lpar);
return 0; }
10078 case WM_NULL: {$
return 0; }
10083 if (msg == WM_SYSCOMMAND)
switch (wpar)
10085 case _TX_IDM_ABOUT: {$ _txCanvas_OnCmdABOUT (wnd, wpar);
return 0; }
10086 case _TX_IDM_CONSOLE: {$ _txCanvas_OnCmdCONSOLE (wnd, wpar);
return 0; }
10091 $
return DefWindowProc (wnd, msg, wpar, lpar);
10096 bool _txCanvas_OnCREATE (HWND wnd)
10098 $8
if (_TX_ARGUMENT_FAILED (wnd))
return false;
10100 $ _txCanvas_BackBuf[0] = _txBuffer_Create (wnd, NULL, NULL, &_txCanvas_Pixels); assert (_txCanvas_BackBuf[0]);
10101 $ _txCanvas_BackBuf[1] = _txBuffer_Create (wnd, NULL, NULL, NULL); assert (_txCanvas_BackBuf[1]);
10104 $ assert (_txCanvas_RefreshTimer);
10106 $ _txCanvas_UserDCs = new ::std::vector <HDC>;
10108 $ _txCanvas_Window = wnd;
10117 bool _txCanvas_OnDESTROY (HWND wnd)
10119 $8
if (_TX_ARGUMENT_FAILED (wnd))
return false;
10123 $ PostQuitMessage (_txRunning? WM_DESTROY : EXIT_SUCCESS);
10125 $
if (!_txCanvas_Window)
return false;
10133 $
bool locked =
false;
10135 $
if (!locked)
TX_DEBUG_ERROR (
"Cannot lock GDI to free resources");
10139 $
if (_txCanvas_UserDCs && !_txCanvas_UserDCs->empty())
10141 $ txNotifyIcon (NIIF_ERROR, NULL,
"Вы забыли освободить %d HDC.", (
int) _txCanvas_UserDCs->size());
10144 $
for (
size_t i = 0; i < _txCanvas_UserDCs->size(); i++) _txBuffer_Delete (&_txCanvas_UserDCs->at (i));
10145 $ _txCanvas_UserDCs->clear();
10150 $
if (_txCanvas_RefreshTimer) KillTimer (wnd, _txCanvas_RefreshTimer)
asserted;
10152 $
if (_txCanvas_BackBuf[1]) _txBuffer_Delete (&_txCanvas_BackBuf[1])
asserted;
10153 $
if (_txCanvas_BackBuf[0]) _txBuffer_Delete (&_txCanvas_BackBuf[0])
asserted;
10154 $ _txCanvas_Pixels = NULL;
10160 $ _txCanvas_Window = NULL;
10167 bool _txCanvas_OnCLOSE (HWND wnd)
10169 $8
if (_TX_ARGUMENT_FAILED (wnd))
return false;
10170 $
if (!_txCanvas_OK())
return false;
10172 $
if (_txMain && _txRunning &&
10173 txMessageBox (
"Функция main() не завершена. Программа все еще работает. Прервать аварийно?\n\n"
10174 "Лучше подождать, когда main() завершится - это отображается в заголовке окна.",
10181 bool _txCanvas_OnTIMER (HWND wnd, WPARAM)
10183 $8
if (_TX_ARGUMENT_FAILED (wnd))
return false;
10185 $
if (_txCanvas_RefreshLock > 0 || !_txRunning)
return false;
10187 $ InvalidateRect (wnd, NULL,
false)
asserted;
10195 bool _txCanvas_OnPAINT (HWND wnd)
10197 $8
if (_TX_ARGUMENT_FAILED (wnd))
return false;
10198 $
if (!_txCanvas_OK())
return false;
10200 $
bool forceRedraw = GetAsyncKeyState (VK_MENU) && GetAsyncKeyState (VK_CONTROL) &&
10201 GetAsyncKeyState (VK_SHIFT) && GetAsyncKeyState (VK_SNAPSHOT);
10203 $ PAINTSTRUCT ps = {};
10204 $ HDC wndDc = BeginPaint (wnd, &ps);
10205 $
if (!wndDc)
return false;
10207 $ HDC dc0 = _txCanvas_BackBuf[0],
10208 dc1 = _txCanvas_BackBuf[1];
10211 $ GetClientRect (wnd, &r)
asserted;
10212 $ POINT wndSize = { r.right - r.left, r.bottom - r.top };
10216 $
if ((_txCanvas_RefreshLock <= 0 || forceRedraw) &&
10219 $ Win32::BitBlt (dc1, 0, 0, dcSize.x, dcSize.y, dc0, 0, 0, SRCCOPY);
10221 $
if (_txConsole >= 0)
10222 {$ _txConsole_Draw (dc1); }
10233 $
if (_txCanvas_RefreshLock != 100500)
10237 $
_txSwapBuffers (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, dcSize.x, dcSize.y, SRCCOPY);
10239 else if (dcSize.x == wndSize.x && dcSize.y == wndSize.y)
10241 $ Win32::BitBlt (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, SRCCOPY);
10245 $ Win32::SetStretchBltMode (wndDc, HALFTONE);
10246 $ Win32::StretchBlt (wndDc, 0, 0, wndSize.x, wndSize.y, dc1, 0, 0, dcSize.x, dcSize.y, SRCCOPY);
10257 bool _txCanvas_OnCHAR (HWND, WPARAM ch, LPARAM info)
10259 $8 INPUT_RECORD evt[2] = {};
10261 $ evt[0].EventType = KEY_EVENT;
10262 $ evt[0].Event.KeyEvent.bKeyDown =
true;
10263 $ evt[0].Event.KeyEvent.wRepeatCount = 1;
10264 $ evt[0].Event.KeyEvent.uChar.AsciiChar = (char) (ch);
10265 $ evt[0].Event.KeyEvent.wVirtualScanCode = (WORD) (info >> 16);
10266 $ evt[0].Event.KeyEvent.wVirtualKeyCode = (WORD) MapVirtualKey ((WORD) (info >> 16), 3);
10267 $ evt[0].Event.KeyEvent.dwControlKeyState = 0;
10270 $ evt[1].Event.KeyEvent.bKeyDown =
false;
10272 $ DWORD written = 0;
10273 $ WriteConsoleInput (GetStdHandle (STD_INPUT_HANDLE), evt, 2, &written);
10280 bool _txCanvas_OnKEY (HWND, WPARAM vk, LPARAM info,
bool down)
10282 $8 INPUT_RECORD evt = {};
10284 $ evt.EventType = KEY_EVENT;
10285 $ evt.Event.KeyEvent.bKeyDown = down;
10286 $ evt.Event.KeyEvent.wRepeatCount = 1;
10287 $ evt.Event.KeyEvent.uChar.AsciiChar = (char) MapVirtualKey ((WORD) vk, 2);
10288 $ evt.Event.KeyEvent.wVirtualScanCode = (WORD) (info >> 16);
10289 $ evt.Event.KeyEvent.wVirtualKeyCode = (WORD) vk;
10290 $ evt.Event.KeyEvent.dwControlKeyState = (DWORD) (info & (1 << (24-1)))? ENHANCED_KEY : 0;
10292 $
if (evt.Event.KeyEvent.uChar.AsciiChar)
return false;
10294 $ DWORD written = 0;
10295 $ WriteConsoleInput (GetStdHandle (STD_INPUT_HANDLE), &evt, 1, &written);
10302 bool _txCanvas_OnMOUSEMOVE (HWND wnd, WPARAM buttons, LPARAM coords)
10304 $8
if (_TX_ARGUMENT_FAILED (wnd))
return false;
10305 $
if (!_txCanvas_OK())
return false;
10307 $
if (_txMousePos.x == -1 && _txMousePos.y == -1)
10309 $ TRACKMOUSEEVENT track = {
sizeof (track), TME_HOVER | TME_LEAVE, wnd, HOVER_DEFAULT };
10310 $ TrackMouseEvent (&track);
10313 $ _txMousePos.x = LOWORD (coords);
10314 $ _txMousePos.y = HIWORD (coords);
10315 $ _txMouseButtons = (unsigned) buttons;
10322 bool _txCanvas_OnMOUSELEAVE (HWND)
10324 $8 _txMousePos.x = -1;
10325 $ _txMousePos.y = -1;
10326 $ _txMouseButtons = 0;
10333 bool _txCanvas_OnCREATEWND (HWND, WPARAM, LPARAM lpar)
10335 $8
if (_TX_ARGUMENT_FAILED (lpar))
return false;
10337 $
const CREATESTRUCT* create = (CREATESTRUCT*) lpar;
10339 $ HWND wnd = CreateWindowEx (create->dwExStyle, create->lpszClass, create->lpszName, create->style,
10340 create->x, create->y, create->cx, create->cy,
10341 create->hwndParent, create->hMenu, NULL, create->lpCreateParams);
10343 $ *(HWND*) create->hInstance = wnd;
10350 bool _txCanvas_OnDESTROYWND (HWND, WPARAM, LPARAM lpar)
10352 $8
if (_TX_ARGUMENT_FAILED (lpar))
return false;
10354 $ DestroyWindow ((HWND) lpar);
10361 bool _txCanvas_OnCmdCONSOLE (HWND wnd, WPARAM cmd)
10363 $8
if (_TX_ARGUMENT_FAILED (wnd))
return false;
10365 $ HWND console = Win32::GetConsoleWindow();
10366 $
if (!console)
return false;
10368 $
bool visible = !!IsWindowVisible (console);
10370 $ ShowWindow (console, visible? SW_HIDE : SW_RESTORE);
10372 $ visible = !!IsWindowVisible (console);
10373 $ CheckMenuItem (GetSystemMenu (wnd,
false), (
int) cmd, visible? MF_CHECKED : MF_UNCHECKED);
10380 bool _txCanvas_OnCmdABOUT (HWND, WPARAM)
10384 #if defined (__MODULE)
10385 #define ABOUT_NAME_ __MODULE
10387 #define ABOUT_NAME_ "TXLib"
10390 #if defined (__MODULE) || defined (__VERSION) || defined (__DESCRIPTION) || defined (__AUTHOR)
10393 #define __MODULE "TXLib" "\n" "#define __MODULE to set the name.\n"
10397 #define __VERSION "(0.000000000)." "\n" "#define __VERSION to set the string value.\n"
10400 #ifndef __DESCRIPTION
10401 #define __DESCRIPTION "(Да, мне лень задать описание)." "\n" "#define __DESCRIPTION to override project role.\n"
10405 #define __AUTHOR "(Непонятно кто)." "\n" "#define __AUTHOR to override this name."
10413 $ _tx_snprintf_s (text,
sizeof (text) - 1,
10417 #
if defined (__MODULE) || defined (__VERSION) || defined (__DESCRIPTION) || defined (__AUTHOR)
10418 __MODULE
" version " __VERSION
"\n" __DESCRIPTION
"\n" "Copyright (c) " __AUTHOR
"\n"
10420 "Здесь могла бы быть Ваша реклама :)\n"
10421 "#define __MODULE to \"your program name\" before including TXLib.h to use this billboard...\n"
10424 "\n" "%s", _txAppInfo());
10426 $
txMessageBox (text,
"About " ABOUT_NAME_, MB_ICONINFORMATION);
10450 #ifndef TX_COMPILED
10452 HWND _txConsole_Attach()
10454 $1 HWND console = Win32::GetConsoleWindow();
10458 $
bool minimizeConsole = ((
TX_CONSOLE_MODE) == SW_HIDE && !_txIsConsoleSubsystem());
10460 $ Win32::TEB* teb = (Win32::TEB*) NtCurrentTeb();
10462 $ assert (teb->ProcessEnvironmentBlock);
10464 $ Win32::RTL_USER_PROCESS_PARAMETERS* params = teb->ProcessEnvironmentBlock->ProcessParameters;
10467 $
if (minimizeConsole)
10472 $ params->dwFlags |= STARTF_USESHOWWINDOW;
10473 $ params->wShowWindow = SW_MINIMIZE;
10477 $ console = Win32::GetConsoleWindow();
10480 $
if (!console)
return NULL;
10484 $ _txConsole_SetUnicodeFont();
10486 $
if (!_txIsConsoleSubsystem())
10487 {$ txReopenStdio(); }
10494 int txSetLocale (
int codepage ,
10495 const char locale[] ,
const wchar_t wLocale[] )
10497 $1
int oldPage = GetConsoleOutputCP();
10503 $ SetConsoleCP (codepage);
10504 $ SetConsoleOutputCP (codepage);
10514 $ setlocale (LC_ALL, locale);
10515 $ setlocale (LC_NUMERIC,
"C");
10520 $
const bool wine = !!Win32::wine_get_version;
10522 $
if (wLocale && !wine)
10524 $ _wsetlocale (LC_ALL, wLocale);
10525 $ _wsetlocale (LC_NUMERIC, L
"C");
10537 void txReopenStdio()
10548 $ f = _fdopen (_open_osfhandle ((intptr_t) GetStdHandle (STD_INPUT_HANDLE), _O_TEXT),
"r"); assert (f); *stdin = *f;
10549 $ f = _fdopen (_open_osfhandle ((intptr_t) GetStdHandle (STD_OUTPUT_HANDLE), _O_TEXT),
"w"); assert (f); *stdout = *f;
10550 $ f = _fdopen (_open_osfhandle ((intptr_t) GetStdHandle (STD_ERROR_HANDLE), _O_TEXT),
"w"); assert (f); *stderr = *f;
10554 $ f = _fdopen (STDIN_FILENO,
"r"); assert (f); *stdin = *f;
10555 $ f = _fdopen (STDOUT_FILENO,
"w"); assert (f); *stdout = *f;
10556 $ f = _fdopen (STDERR_FILENO,
"w"); assert (f); *stderr = *f;
10560 $ setvbuf (stdin, NULL, _IONBF, 0);
10561 $ setvbuf (stdout, NULL, _IONBF, 0);
10562 $ setvbuf (stderr, NULL, _IONBF, 0);
10564 $ ::std::ios::sync_with_stdio();
10569 inline bool _txConsole_OK()
10571 return Win32::GetConsoleWindow() != NULL;
10576 bool _txConsole_Detach (
bool activate)
10578 $1 HWND console = Win32::GetConsoleWindow();
10579 $
if (!console)
return false;
10581 $ EnableWindow (console,
true);
10585 $
if (!IsWindowVisible (console))
10586 {$ ShowWindow (console, SW_MINIMIZE); }
10588 $ _txActivateWindow (console, 0xFF);
10593 $
return !!FreeConsole();
10599 bool _txConsole_Draw (HDC dc)
10601 $8
if (_TX_HDC_FAILED (dc))
return false;
10603 $ HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
10605 $ CONSOLE_SCREEN_BUFFER_INFO con = {};
10606 $ BOOL ok = GetConsoleScreenBufferInfo (out, &con);
10607 $
if (!ok)
return false;
10609 $ POINT size = { con.srWindow.Right - con.srWindow.Left + 1,
10610 con.srWindow.Bottom - con.srWindow.Top + 1 };
10612 $ SIZE fontSz = { 12, 16 };
10613 $ Win32::GetTextExtentPoint32 (dc,
"W", 1, &fontSz)
asserted;
10615 $ COLORREF pal [16] = { 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 0xC0C0C0,
10616 0x808080, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF };
10618 $
for (
short y = 0; y < size.y; y++)
10622 COORD coord = { (short) (con.srWindow.Left), (short) (y + con.srWindow.Top) };
10625 if (!ReadConsoleOutputCharacter (out, chr,
sizearr (chr) - 1, coord, &read))
continue;
10626 if (!ReadConsoleOutputAttribute (out, atr,
sizearr (atr) - 1, coord, &read))
continue;
10628 for (
int x = 0, xEnd = size.x; x < size.x; x = xEnd)
10630 Win32::SetTextColor (dc, pal [ atr[x] & 0x0F]);
10631 Win32::SetBkColor (dc, pal [(atr[x] >> 4) & 0x0F]);
10632 Win32::SetBkMode (dc, (atr[x] & 0xF0)? OPAQUE : TRANSPARENT);
10634 for (xEnd = x+1; xEnd < size.x && atr[xEnd] == atr[x]; xEnd++) {;}
10636 Win32::TextOut (dc,
ROUND (fontSz.cx * (x + con.srWindow.Left)),
10641 $ Win32::SetTextColor (dc, pal [ con.wAttributes & 0x0F]);
10642 $ Win32::SetBkColor (dc, pal [(con.wAttributes >> 4) & 0x0F]);
10643 $ Win32::SetBkMode (dc, TRANSPARENT);
10645 $
if (_txConsole_IsBlinking &&
10646 In (std::nomeow, con.dwCursorPosition, con.srWindow) &&
10648 GetForegroundWindow() ==
txWindow())
10650 $ Win32::TextOut (dc,
ROUND (fontSz.cx * (con.dwCursorPosition.X - con.srWindow.Left)),
10651 ROUND (fontSz.cy * (con.dwCursorPosition.Y - con.srWindow.Top)) + 1,
10664 #ifndef TX_COMPILED
10666 bool _txConsole_SetUnicodeFont()
10668 $
const bool wine = !!Win32::wine_get_version;
10672 $ Win32::GetNumberOfConsoleFonts = NULL;
10673 $ Win32::GetCurrentConsoleFont = NULL;
10674 $ Win32::SetConsoleFont = NULL;
10681 $1
if (Win32::GetCurrentConsoleFontEx && Win32::SetCurrentConsoleFontEx)
10683 $ HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
10685 $ Win32::CONSOLE_FONT_INFOEX info = {
sizeof (info) };
10686 $
if (!Win32::GetCurrentConsoleFontEx (out,
false, &info))
return false;
10688 $ info.FontFamily = 0x36;
10689 $
if (!*info.FaceName) info.dwFontSize.Y = (SHORT) (info.dwFontSize.Y + 2);
10691 $
if (wcsncmp (info.FaceName, L
"Consolas",
sizearr (info.FaceName)) != 0)
10692 {$ wcsncpy_s (info.FaceName,
sizearr (info.FaceName), L
"Lucida Console",
sizearr (info.FaceName)); }
10694 $
return !!Win32::SetCurrentConsoleFontEx (out,
false, &info);
10699 $
const unsigned uniFont = 10;
10700 $
const unsigned uniSize = 20;
10705 $ HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
10707 $
unsigned fonts = _TX_CALL (Win32::GetNumberOfConsoleFonts, ());
10708 $
if (fonts && fonts <= uniFont)
10710 $ HRESULT init = Win32::CoInitialize (NULL);
10713 $
char link [MAX_PATH] =
"";
10714 $ getenv_s (&sz, link,
sizeof (link) - 1,
"TEMP");
10715 $ strncat_s (link,
sizeof (link),
"\\~txLink.lnk",
sizeof (link) - 1);
10717 $
char comspec [MAX_PATH] =
"";
10718 $ getenv_s (&sz, comspec,
sizeof (comspec),
"COMSPEC");
10720 $ (void) _unlink (link);
10722 $ _txCreateShortcut (link, comspec,
"/c exit", NULL, NULL, SW_SHOWMINNOACTIVE, NULL, 0, uniSize)
asserted;
10724 $ ok = (Win32::ShellExecuteA (NULL, NULL, link, NULL, NULL, SW_SHOWMINNOACTIVE) > (
void*)32);
10725 if (ok) {$ _txWaitFor (FindWindow (NULL,
"~txLink"),
_TX_TIMEOUT); }
10727 $ (void) _unlink (link);
10729 $
if (init == S_OK) Win32::CoUninitialize();
10734 $ Win32::CONSOLE_FONT_INFO cur = {};
10735 $ _TX_CALL (Win32::GetCurrentConsoleFont, (out,
false, &cur));
10737 $ ok &= (cur.nFont >= uniFont);
10738 if (!ok) {$ ok &= _TX_CALL (Win32::SetConsoleFont, (out, uniFont)); }
10740 $ HWND console = Win32::GetConsoleWindow();
10741 $ InvalidateRect (console, NULL,
false);
10742 $ UpdateWindow (console);
10752 #define _TX_TRY { goto __tx_try; } __tx_try: { int __tx_error = S_OK; (void)__tx_error;
10753 #define _TX_CHECKED( cmd ) { if (FAILED (__tx_error = (cmd))) goto __tx_catch; }
10754 #define _TX_FAIL { __tx_error = E_FAIL; goto __tx_catch; }
10755 #define _TX_RETRY { __tx_error = S_OK; goto __tx_try; }
10756 #define _TX_OK ( SUCCEEDED (__tx_error) )
10757 #define _TX_CATCH goto __tx_finally; __tx_catch:
10758 #define _TX_RETURN goto __tx_finally;
10759 #define _TX_FINALLY __tx_finally:
10760 #define _TX_ENDTRY }
10767 #ifndef TX_COMPILED
10769 bool _txCreateShortcut (
const char shortcutName[],
10770 const char fileToLink[],
const char args[] ,
const char workDir[] ,
10771 const char description[] ,
int cmdShow ,
const char iconFile[] ,
int iconIndex ,
10772 int fontSize , COORD bufSize , COORD wndSize , COORD wndOrg )
10774 $1
if (_TX_ARGUMENT_FAILED (shortcutName && *shortcutName))
return false;
10775 $
if (_TX_ARGUMENT_FAILED (fileToLink && *fileToLink))
return false;
10777 #if defined (__IShellLinkDataList_INTERFACE_DEFINED__)
10779 $ IShellLink* shellLink = NULL;
10780 $ IShellLinkDataList* dataList = NULL;
10781 $ IPersistFile* file = NULL;
10783 $ HRESULT init = Win32::CoInitialize (NULL);
10787 $ _TX_CHECKED (Win32::CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, Win32::IID_IShellLink, (
void**) &shellLink));
10788 $
if (!shellLink) _TX_FAIL;
10790 $ shellLink->SetPath (fileToLink);
10791 $ shellLink->SetArguments (args);
10792 $ shellLink->SetWorkingDirectory (workDir);
10793 $ shellLink->SetDescription (description);
10794 $ shellLink->SetShowCmd (cmdShow);
10795 $ shellLink->SetIconLocation (iconFile, iconIndex);
10797 $ _TX_CHECKED (shellLink->QueryInterface (Win32::IID_IShellLinkDataList, (
void**) &dataList));
10798 $
if (!dataList) _TX_FAIL;
10800 $ Win32::NT_CONSOLE_PROPS props =
10801 {{
sizeof (props), NT_CONSOLE_PROPS_SIG},
10803 FOREGROUND_LIGHTGRAY,
10804 FOREGROUND_MAGENTA | BACKGROUND_WHITE,
10805 {bufSize.X, bufSize.Y},
10806 {wndSize.X, wndSize.Y},
10807 {wndOrg.X, wndOrg.Y},
10810 {0, (short) fontSize},
10811 0x36, 400, L
"Lucida Console",
10816 {0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 0xC0C0C0,
10817 0x808080, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF}
10820 $ _TX_CHECKED (dataList->AddDataBlock (&props));
10822 $ _TX_CHECKED (shellLink->QueryInterface (Win32::IID_IPersistFile, (
void**) &file));
10823 $
if (!file) _TX_FAIL;
10825 $
wchar_t wName[MAX_PATH] = L
"";
10826 $ MultiByteToWideChar (
_TX_CODEPAGE, 0, shortcutName, -1, wName, MAX_PATH) || ZeroMemory (wName,
sizeof (wName));
10828 $ _TX_CHECKED (file->Save (wName,
true));
10834 if (file) {$ file ->Release(); }
10835 if (dataList) {$ dataList ->Release(); }
10836 if (shellLink) {$ shellLink->Release(); }
10838 if (init == S_OK) {$ Win32::CoUninitialize(); }
10845 (void) args; (void) workDir, (
void) description; (void) cmdShow; (void) iconFile; (void) iconIndex;
10846 (void) fontSize; (void) bufSize; (void) wndSize; (void) wndOrg;
10868 #ifndef TX_COMPILED
10870 HDC _txBuffer_Create (HWND wnd,
const POINT* size , HBITMAP bitmap , RGBQUAD** pixels )
10874 $ HDC wndDC = GetDC (wnd);
10875 $
if (!wndDC)
return NULL;
10877 $ POINT sz = { 1, 1 };
10878 $
if (size) sz = *size;
10880 $
if (!size && wnd)
10883 $ GetClientRect (wnd, &r)
asserted;
10885 $ sz.x = r.right - r.left;
10886 $ sz.y = r.bottom - r.top;
10891 $ BITMAP bmap = {};
10892 $ Win32::GetObject (bitmap,
sizeof (bmap), &bmap)
asserted;
10894 $ sz.x = bmap.bmWidth;
10895 $ sz.y = bmap.bmHeight;
10898 $ RGBQUAD* buf = NULL;
10899 $
if (!pixels) pixels = &buf;
10901 $ HDC dc = Win32::CreateCompatibleDC (wndDC);
10902 $
if (!dc)
TX_DEBUG_ERROR (
"Cannot create buffer: CreateCompatibleDC() failed");
10904 #ifndef _TX_DIB_FIX
10905 #define _TX_DIB_FIX
10908 $ BITMAPINFO info = {{
sizeof (info), sz.x, _TX_DIB_FIX sz.y, 1, WORD (
sizeof (RGBQUAD) * 8), BI_RGB }};
10910 $ HBITMAP bmap = bitmap? bitmap : Win32::CreateDIBSection (NULL, &info, DIB_RGB_COLORS, (
void**) pixels, NULL, 0);
10911 $
if (!bmap)
TX_DEBUG_ERROR (
"Cannot create buffer: CreateCompatibleBitmap() failed");
10913 $ Win32::SelectObject (dc, bmap)
asserted;
10919 $ RGBQUAD black = { 0, 0, 0, 255 };
10920 $
for (
int i = 0; i < sz.x * sz.y; i++) (*pixels)[i] = black;
10923 {$ Win32::PatBlt (dc, 0, 0, sz.x, sz.y, BLACKNESS)
asserted; }
10926 $ ReleaseDC (wnd, wndDC)
asserted;
10933 bool _txBuffer_Delete (HDC* dc)
10935 $1
if (_TX_ARGUMENT_FAILED (dc))
return false;
10936 $
if ( !*dc)
return false;
10937 $
if (_TX_HDC_FAILED (*dc))
return false;
10939 $
if (!Win32::GetObjectType (Win32::GetCurrentObject (*dc, OBJ_BITMAP)))
return false;
10943 $ _txBuffer_Select (Win32::GetStockObject (NULL_PEN), *dc)
asserted;
10944 $ _txBuffer_Select (Win32::GetStockObject (NULL_BRUSH), *dc)
asserted;
10945 $ _txBuffer_Select (Win32::GetStockObject (SYSTEM_FONT), *dc)
asserted;
10946 $ _txBuffer_Select (_txStockBitmap, *dc);
10948 $ Win32::DeleteObject (Win32::GetCurrentObject (*dc, OBJ_BITMAP))
asserted;
10959 bool _txBuffer_Select (HGDIOBJ obj, HDC dc )
10961 $1
if (!obj)
return false;
10962 $
if (_TX_HDC_FAILED (dc))
return false;
10964 $
if (!Win32::GetObjectType (obj))
TX_DEBUG_ERROR (
"Invalid GDI object type");
10968 $ obj = Win32::SelectObject (dc, obj);
10969 $
if (obj) Win32::DeleteObject (obj);
10971 $
return obj != NULL;
10986 #ifndef TX_COMPILED
10988 const char* _txError (
const char* file ,
int line ,
const char* func ,
unsigned color ,
10989 const char* msg , ...)
10991 $1 va_list arg; va_start (arg, msg);
10992 $$
const char* what = _txProcessError (file, line, func, color, msg, arg);
10995 if (!(msg && msg[0] ==
'\a'))
return what;
11010 #ifndef TX_COMPILED
11012 void _txOnSignal (
int sig ,
int fpe )
11014 $1
if (!sig && !fpe)
11016 $ signal (SIGSEGV, (
void(*)(
int))(uintptr_t)_txOnSignal) != SIG_ERR
asserted;
11017 $ signal (SIGFPE, (
void(*)(
int))(uintptr_t)_txOnSignal) != SIG_ERR
asserted;
11018 $ signal (SIGABRT, (
void(*)(
int))(uintptr_t)_txOnSignal) != SIG_ERR
asserted;
11019 $ signal (SIGILL, (
void(*)(
int))(uintptr_t)_txOnSignal) != SIG_ERR
asserted;
11020 $ signal (SIGTERM, (
void(*)(
int))(uintptr_t)_txOnSignal) != SIG_ERR
asserted;
11024 txOutputDebugPrintf (
"%s - WARNING: %s (%d, %d) called\n", _TX_VERSION, __func__, sig, fpe);
11026 #define GET_DESCR_(str, code, descr) case (code): {$ (str) = " " #code ": " descr; break; }
11028 $
const char* sSig =
"Неизвестный тип сигнала ;
$ switch (sig)
{
GET_DESCR_ (sSig, SIGSEGV, "Доступ по неверному указателю. Ставьте ассерты!")
GET_DESCR_ (sSig, SIGILL, "Попытка выполнить недопустимую операцию. Проверьте указатели на функции.")
GET_DESCR_ (sSig, SIGABRT, "Аварийное завершение программы, вызвана функция abort().")
GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call";
11032 GET_DESCR_ (sSig, SIGSEGV,
"Доступ по неверному указателю. Ставьте ассерты!")
11033 GET_DESCR_ (sSig, SIGILL, "Попытка выполнить недопустимую операцию. Проверьте указатели на функции.")
GET_DESCR_ (sSig, SIGABRT, "Аварийное завершение программы, вызвана функция abort().")
GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call выполнить недопустимую операцию. Проверьте указатели на функции.")
GET_DESCR_ (sSig, SIGABRT, "Аварийное завершение программы, вызвана функция abort().")
GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call недопустимую операцию. Проверьте указатели на функции.")
GET_DESCR_ (sSig, SIGABRT, "Аварийное завершение программы, вызвана функция abort().")
GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call указатели на функции.")
GET_DESCR_ (sSig, SIGABRT, "Аварийное завершение программы, вызвана функция abort().")
GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call на функции ")
GET_DESCR_ (sSig, SIGABRT, "Аварийное завершение программы, вызвана функция abort().")
GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call.")
11034 GET_DESCR_ (sSig, SIGABRT, "Аварийное завершение программы, вызвана функция abort().")
GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call завершение программы вызвана функция abort().")
GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call, вызвана функция abort().")
GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call функция abort().")
11035 GET_DESCR_ (sSig, SIGTERM, "Получен сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call сигнал принудительного завершения программы.")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call завершения программы ")
GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call.")
11036 GET_DESCR_ (sSig, SIGFPE, "Грубая ошибка в вычислениях.")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call вычислениях ")
default: break; //-V2522
}
$ const char* sFPE = "";
#if defined (_MSC_VER)
// MSVC provides the FPE code as a MS extension.
// See: https://msdn.microsoft.com/ru-ru/library/xdkz3x12.aspx
$ if (sig == SIGFPE) switch (fpe)
{
GET_DESCR_ (sFPE, _FPE_INVALID, "Результат неверен.")
GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call.")
11040 $ const
char* sFPE = "";
11042 #if defined (_MSC_VER)
11047 $
if (sig == SIGFPE)
switch (fpe)
11049 GET_DESCR_ (sFPE, _FPE_INVALID,
"Результат неверен.")
11050 GET_DESCR_ (sFPE, _FPE_DENORMAL, "Денормализация.")
11051 GET_DESCR_ (sFPE, _FPE_ZERODIVIDE, "Деление на ноль.")
GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call на ноль.")
11052 GET_DESCR_ (sFPE, _FPE_OVERFLOW, "Результат слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call слишком большой.")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call большой ")
GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call.")
11053 GET_DESCR_ (sFPE, _FPE_UNDERFLOW, "Результат слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call слишком маленький.")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call маленький ")
GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call.")
11054 GET_DESCR_ (sFPE, _FPE_INEXACT, "Результат неточен.")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call неточен ")
GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа.")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call.")
11055 GET_DESCR_ (sFPE, _FPE_UNEMULATED, "Операция не поддерживается.")
11056 GET_DESCR_ (sFPE, _FPE_SQRTNEG, "Квадратный корень из отрицательного числа ")
GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call.")
11057 GET_DESCR_ (sFPE, _FPE_STACKOVERFLOW, "Переполнение стека сопроцессора.")
GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call сопроцессора.")
11058 GET_DESCR_ (sFPE, _FPE_STACKUNDERFLOW, "В стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call стеке сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call сопроцессора не хватает данных.")
GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call данных.")
11059 GET_DESCR_ (sFPE, _FPE_EXPLICITGEN, "Явный вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call вызов исключения.")
default: break; //-V2522
}
#else
$ fpe = 0;
#endif
#undef GET_DESCR_
$ signal (sig, (void(*)(int))(uintptr_t)_txOnSignal);
$ Win32::_fpreset();
$ _TX_UNEXPECTED ("\a\t"
"signal (%d, 0x%02X):%s%s "
"%s%s"
"С помощью функции signal() вы можете сами обработать эту ошибку.",
sig, (unsigned) fpe, sSig, sFPE,
((_txDumpSE[1] == '\n')? "" : "\n\n"), _txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnTerminate()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
// From: http://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/vterminate.cc
$1 static int terminating = 0;
if (terminating++) {$ _TX_UNEXPECTED ("\a" "std::terminate() вызвана рекурсивно."); return; }
$ if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("\t\a"
"std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
"или другая фатальная ошибка C++. "
"%s"
"Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
"разбирайтесь, в чем дело.\n\n"
"С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnUnexpected()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1 if (!*_txDumpSE)
{$ _txDumpExceptionCPP (_txDumpSE + 1, sizeof (_txDumpSE) - 2); }
$ _TX_UNEXPECTED ("std::unexpected(): Необработанное исключение.\n\n"
"Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
"спецификацию исключений для функций, проверьте, не нарушена ли она."
"%s"
"С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
_txDumpSE + 1);
}
//-----------------------------------------------------------------------------------------------------------------
int _txOnMatherr (_exception* exc)
{
txOutputDebugPrintf ("%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (void*) exc);
$1 assert (exc);
const char* sType = "Неизвестный тип исключения";
#if !defined (__CYGWIN__)
#define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
$ switch (exc->type)
{
GET_DESCR_ (_DOMAIN, "Нарушение области определения");
GET_DESCR_ (_SING, "Сингулярность аргумента");
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call исключения.")
11069 $ signal (sig, (
void(*)(
int))(uintptr_t)_txOnSignal);
11071 $ Win32::_fpreset();
11073 $ _TX_UNEXPECTED (
"\a\t"
11074 "signal (%d, 0x%02X):%s%s "
11076 "С помощью функции signal() вы можете сами обработать эту ошибку.",
11077 sig, (
unsigned) fpe, sSig, sFPE,
11078 ((_txDumpSE[1] ==
'\n')?
"" :
"\n\n"), _txDumpSE + 1);
11083 void _txOnTerminate()
11089 $1
static int terminating = 0;
11090 if (terminating++) {$ _TX_UNEXPECTED (
"\a" "std::terminate() вызвана рекурсивно.");
return; }
11093 {$ _txDumpExceptionCPP (_txDumpSE + 1,
sizeof (_txDumpSE) - 2); }
11095 $ _TX_UNEXPECTED (
"\t\a"
11096 "std::terminate(): Неперехваченное исключение в функции main() или в деструкторе, "
11097 "или другая фатальная ошибка C++. "
11099 "Используйте try/catch блоки, перехватывайте catch (...), проверяйте вызовы виртуальных функций, "
11100 "разбирайтесь, в чем дело.\n\n"
11101 "С помощью std::set_terminate() вы можете сами обработать эту ошибку." + !*_txDumpSE,
11107 void _txOnUnexpected()
11111 $1
if (!*_txDumpSE)
11112 {$ _txDumpExceptionCPP (_txDumpSE + 1,
sizeof (_txDumpSE) - 2); }
11114 $ _TX_UNEXPECTED (
"std::unexpected(): Необработанное исключение.\n\n"
11115 "Проверьте свои catch-блоки. Перехватите catch (...). Если вы (зря) используете "
11116 "спецификацию исключений для функций, проверьте, не нарушена ли она."
11118 "С помощью catch (...) в main() вы можете сами обработать эту ошибку.",
11124 int _txOnMatherr (_exception* exc)
11126 txOutputDebugPrintf (
"%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (
void*) exc);
11130 const char* sType =
"Неизвестный тип исключения";
11132 #if !defined (__CYGWIN__)
11134 #define GET_DESCR_(code, descr) case (code): {$ sType = "(" #code "): " descr; break; }
11136 $
switch (exc->type)
11138 GET_DESCR_ (_DOMAIN,
"Нарушение области определения");
11139 GET_DESCR_ (_SING,
"Сингулярность аргумента );
GET_DESCR_ (_PLOSS, "Частичная потеря значимости");
GET_DESCR_ (_TLOSS, "Полная потеря значимости");
GET_DESCR_ (_OVERFLOW, "Результат слишком большой");
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call");
11140 GET_DESCR_ (_PLOSS,
"Частичная потеря значимости");
11141 GET_DESCR_ (_TLOSS,
"Полная потеря значимости");
11142 GET_DESCR_ (_OVERFLOW,
"Результат слишком большой );
GET_DESCR_ (_UNDERFLOW, "Результат слишком маленький");
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call");
11143 GET_DESCR_ (_UNDERFLOW,
"Результат слишком маленький );
default: break; //-V2522
}
#undef GET_DESCR_
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
"С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
#else
$ _TX_UNEXPECTED ("_matherr(): Математическая ошибка: %s.", sType);
#endif
return 0;
}
//-----------------------------------------------------------------------------------------------------------------
tx_noreturn void _txOnNewHandlerAnsi()
{
txOutputDebugPrintf ("%s - WARNING: %s() called\n", _TX_VERSION, __func__);
$1
$ _TX_UNEXPECTED ("operator new: Ошибка выделения памяти.\n\n"
"С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
"и где-нибудь найти недостающую память.");
$ throw std::bad_alloc();
}
//-----------------------------------------------------------------------------------------------------------------
void _txOnSecurityErrorAnsi (const char* msg, void* ptr, int code)
{
txOutputDebugPrintf ("%s - WARNING: %s (%s, 0x%p, %d) call");
11149 $ _TX_UNEXPECTED (
"_matherr(): Математическая ошибка %d %s в функции %s (%g, [%g]). Она вернет значение %g.\n\n"
11150 "С помощью __setusermatherr() вы можете сами обработать эту ошибку.",
11151 exc->type, sType, exc->name, exc->arg1, exc->arg2, exc->retval);
11154 $ _TX_UNEXPECTED (
"_matherr(): Математическая ошибка: %s.", sType);
11163 tx_noreturn
void _txOnNewHandlerAnsi()
11167 $ _TX_UNEXPECTED (
"operator new: Ошибка выделения памяти.\n\n"
11168 "С помощью std::set_new_handler() вы можете сами обработать эту ошибку "
11169 "и где-нибудь найти недостающую память.");
11171 $
throw std::bad_alloc();
11176 void _txOnSecurityErrorAnsi (
const char* msg,
void* ptr,
int code)
11178 txOutputDebugPrintf (
"%s - WARNING: %s (%s, 0x%p, %d) called\n", _TX_VERSION, __func__, msg, ptr, code);
11183 $ _TX_UNEXPECTED (
"\a"
11184 "Ошибка переполнения буфера %d: %s в %.20s (0x%p). Ставьте ассерты!\n\n"
11185 "С помощью std::set_constraint_handler_s() вы можете сами обработать эту ошибку "
11186 "и постараться не выходить за границы массивов.",
11187 code, msg, (
char*) ptr, ptr);
11192 int tx_glGetError (
int setError )
11194 $1 _txOGLError = (setError == INT_MIN)? _TX_CALL (Win32::glGetError, ()) : setError;
11195 $
return _txOGLError;
11207 #if defined (_MSC_VER)
11209 #ifndef TX_COMPILED
11213 int _txOnNewHandler (
size_t size)
11215 txOutputDebugPrintf (
"%s - WARNING: %s (0x%p) called\n", _TX_VERSION, __func__, (
void*)(uintptr_t) size);
11217 $ _TX_UNEXPECTED (
"operator new: Ошибка выделения %llu байт памяти.\n\n"
11218 "С помощью _set_new_handler() вы можете сами обработать эту ошибку "
11219 "и где-нибудь найти недостающую память.", (
unsigned long long) size);
11221 $
throw std::bad_alloc();
11226 void _txOnSecurityError (
int code,
void* addr)
11228 txOutputDebugPrintf (
"%s - WARNING: %s (%d, 0x%p) called\n", _TX_VERSION, __func__, code, addr);
11230 $ _TX_UNEXPECTED (
"\a"
11231 "Ошибка переполнения буфера %d (_SECERR_BUFFER_OVERRUN). Ставьте ассерты!\n\n"
11232 "С помощью _set_security_error_handler() вы можете сами обработать эту ошибку "
11233 "и более торжественно завершить программу. Ставьте же ассерты.", code);
11238 void _txOnPureCall()
11242 $ _TX_UNEXPECTED (
"\a"
11243 "Вызвана чисто виртуальная функция. Такое бывает, например, в конструкторах "
11244 "или деструкторах базовых классов - не вызывайте там таких функций.\n\n"
11245 "С помощью _set_purecall_handler() вы можете сами обработать эту ошибку "
11246 "и проверить свое знание С++ :)");
11251 void _txOnInvalidParam (
const wchar_t* wExpr,
const wchar_t* wFunc,
const wchar_t* wFile,
unsigned int line, uintptr_t addr)
11253 txOutputDebugPrintf (
"%s - WARNING: %s (%S, %S, %S, %d, 0x%p) called\n", _TX_VERSION, __func__, wExpr, wFunc, wFile, line, addr);
11261 file [MAX_PATH] =
"[Unknowm file]";
11263 $ WideCharToMultiByte (
_TX_CODEPAGE, 0, wExpr, -1, expr,
sizeof (expr) - 1, NULL, NULL);
11264 $ WideCharToMultiByte (
_TX_CODEPAGE, 0, wFunc, -1, func,
sizeof (func) - 1, NULL, NULL);
11265 $ WideCharToMultiByte (
_TX_CODEPAGE, 0, wFile, -1, file,
sizeof (file) - 1, NULL, NULL);
11267 $$ _txError (file, (
int) line, func, 0,
"\a"
11268 "В функцию %s передан неверный параметр: неверно, что %s. Не надо так.\n\n"
11269 "С помощью _set_invalid_parameter_handler() вы можете сами обработать эту ошибку.", func, expr);
11274 #if defined (_CLANG_VER) && !defined (_MSC_VER)
11276 void _txLibCppDebugFunction (std::__libcpp_debug_info
const& info)
11280 $$ _txError (info.__file_, info.__line_, NULL, 0,
"\a"
11281 "Оказалось неверно, что %s (%s). Не надо так.\n\n"
11282 "С помощью std::__libcpp_debug_function вы можете сами обработать эту ошибку.", info.__pred_, info.__msg_);
11289 #pragma runtime_checks ("", off)
11291 int _txOnRTCFailure (
int type,
const char* file,
int line,
const char* module,
const char* format, ...)
11293 txOutputDebugPrintf (
"%s - WARNING: %s (%d, %s, %d, %s, %s) called\n", _TX_VERSION, __func__, type, file, line, module, format);
11295 $5
static long running = 0;
11296 $
while (InterlockedExchange (&running, 1)) Sleep (0);
11302 $
int nErrors = _RTC_NumErrors();
11303 $
int* errors = NULL;
11304 $
try { errors = (
int*) _alloca (nErrors *
sizeof (*errors)); }
catch (...) {;}
11307 $
for (
int i = 0; i < nErrors; i++) *(errors? &errors[i] : &err) = _RTC_SetErrorType ((_RTC_ErrorNumber) i, _RTC_ERRTYPE_IGNORE);
11311 $ va_list arg; va_start (arg, format);
11312 $ _tx_vsnprintf_s (text,
sizeof (text) - 1, format, arg);
11313 $
auto error = (_RTC_ErrorNumber) va_arg (arg,
int );
11316 $
const char* sType =
"type";
11320 case _CRT_ERROR: $ sType =
"ошибка";
break;
11321 case _CRT_ASSERT: $ sType =
"логическая ошибка";
break;
11322 case _CRT_WARN: $ sType =
"возможная ошибка";
break;
11326 $
const char* sError = _RTC_GetErrDesc (error);
11328 $$ _txError (file, line, NULL, 0,
"\a"
11329 "Сбой проверки выполнения машинного кода: %s %d (%s): %s в модуле %s.", sType, error, sError, text, module);
11335 #if defined (_MSC_VER)
11336 #pragma warning (push)
11337 #pragma warning (disable: 6385)
11340 $
for (
int i = 0; i < nErrors; i++) _RTC_SetErrorType ((_RTC_ErrorNumber) i, (errors? errors[i] : _CRT_ERROR));
11342 #if defined (_MSC_VER)
11343 #pragma warning (pop)
11346 $ InterlockedExchange (&running, 0);
11350 #pragma runtime_checks ("", restore)
11354 int _txOnAllocHook (
int type,
void* data,
size_t size,
int use,
long request,
const unsigned char* file,
int line)
11356 #if (_TX_ALLOW_TRACE +0 >= 4)
11358 static _tx_thread
int recursive = 0;
11359 if (recursive)
return true;
11362 #if (_TX_ALLOW_TRACE +0 <= 10)
11363 if (!size)
return true;
11366 #define GET_DESCR_(str, type) case (type): { str = #type; break; }
11368 const char* sType =
"Unknown type";
11369 const char* sUse =
"Unknown use";
11371 switch (_BLOCK_TYPE (type))
11373 GET_DESCR_ (sType, _HOOK_ALLOC);
11374 GET_DESCR_ (sType, _HOOK_REALLOC);
11375 GET_DESCR_ (sType, _HOOK_FREE);
11381 GET_DESCR_ (sUse, _NORMAL_BLOCK);
11382 GET_DESCR_ (sUse, _CRT_BLOCK);
11383 GET_DESCR_ (sUse, _CLIENT_BLOCK);
11384 GET_DESCR_ (sUse, _FREE_BLOCK);
11385 GET_DESCR_ (sUse, _IGNORE_BLOCK);
11391 _txTrace ((
const char*) file, line, NULL,
"%*s"
11392 "_txOnAllocHook (type = 0x%02X (%-*s), subtype =0x%X, data = 0x%p, size = 0x%p, use = 0x%02X (%-*s), request = %ld)",
11393 2 * _txLoc::Cur.inTX,
"",
11394 type, 13, sType, _BLOCK_SUBTYPE (type), data, (
void*) size, use, 13, sUse, request);
11400 UNREFERENCED_PARAMETER (type);
11401 UNREFERENCED_PARAMETER (data);
11402 UNREFERENCED_PARAMETER (size);
11403 UNREFERENCED_PARAMETER (use);
11404 UNREFERENCED_PARAMETER (request);
11405 UNREFERENCED_PARAMETER (file);
11406 UNREFERENCED_PARAMETER (line);
11426 #ifndef TX_COMPILED
11428 long WINAPI _txVectoredExceptionHandler (EXCEPTION_POINTERS* exc)
11432 DWORD code = (exc && exc->ExceptionRecord)? exc->ExceptionRecord->ExceptionCode : 0;
11433 void* addr = (exc && exc->ExceptionRecord)? exc->ExceptionRecord->ExceptionAddress : NULL;
11435 if (code != DBG_PRINTEXCEPTION_C &&
11436 code != DBG_PRINTEXCEPTION_WIDE_C)
11438 txOutputDebugPrintf (
"%s - WARNING: %s (code 0x%08lX, addr 0x%p) called and SKIPPED! (_txProcessSystemWarnings == %d)\n",
11442 return EXCEPTION_CONTINUE_SEARCH;
11446 int inTX = _txLoc::Cur.inTX++;
11448 long ret = _txOnExceptionSEH (exc,
"_txVectoredExceptionHandler");
11450 _txLoc::Cur.inTX = inTX;
11457 long WINAPI _txUnhandledExceptionFilter (EXCEPTION_POINTERS* exc)
11459 int inTX = _txLoc::Cur.inTX++;
11461 long ret = _txOnExceptionSEH (exc,
"_txUnhandledExceptionFilter");
11463 if (_txPrevUEFilter)
11467 int inTX2 = _txLoc::Cur.inTX++;
11469 ret = _txPrevUEFilter (exc);
11471 _txLoc::Cur.inTX = inTX2;
11477 _TX_UNEXPECTED (
"\t\a" "%s"
11478 "С помощью функции _set_se_translator() вы можете сами обработать эту ошибку.\n\n"
11479 "Дополнительно: Сбой вызова стандартного обработчика неперехваченнных исключений SEH." + !*_txDumpSE,
11484 _txLoc::Cur.inTX = inTX;
11490 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI _txOnSetUnhandledExceptionFilter (LPTOP_LEVEL_EXCEPTION_FILTER filter)
11492 $6 _txPrevUEFilter = filter;
11494 return (LPTOP_LEVEL_EXCEPTION_FILTER) _txUnhandledExceptionFilter;
11499 long _txOnExceptionSEH (EXCEPTION_POINTERS* exc,
const char func[])
11501 assert (exc);
if (!exc) {$
return EXCEPTION_CONTINUE_SEARCH; }
11503 assert (exc->ExceptionRecord);
11506 assert (func[3] ==
'V' || func[3] ==
'U');
11508 bool unhExc = (func[3] ==
'U');
11509 DWORD code = (exc && exc->ExceptionRecord)? exc->ExceptionRecord->ExceptionCode : 0;
11510 void* addr = (exc && exc->ExceptionRecord)? exc->ExceptionRecord->ExceptionAddress : NULL;
11512 if (code == DBG_PRINTEXCEPTION_C ||
11513 code == DBG_PRINTEXCEPTION_WIDE_C ||
11514 code == DBG_THREAD_NAME ||
11515 (code == RPC_S_SERVER_UNAVAILABLE && !unhExc) ||
11516 (code == RPC_S_CALL_CANCELLED && !unhExc) ||
11517 (code == EXCEPTION_BREAKPOINT && IsDebuggerPresent()))
11518 return EXCEPTION_CONTINUE_SEARCH;
11520 ptrdiff_t dist = (uintptr_t) addr - (uintptr_t) IsBadReadPtr;
11521 if (0 <= dist && dist <= 256) {$6
return EXCEPTION_CONTINUE_SEARCH; }
11523 dist = (uintptr_t) addr - (uintptr_t) IsBadWritePtr;
11524 if (0 <= dist && dist <= 256) {$6
return EXCEPTION_CONTINUE_SEARCH; }
11526 _txSENumber = _txSENumber + 1;
11527 if (HIBYTE (HIWORD (code)) == 0xC0) _txSEFatalNumber = _txSEFatalNumber + 1;
11529 OutputDebugString (
"\n");
11531 _TX_VERSION, _txSENumber, func, (
unsigned long) code, addr);
11533 $6
if (*(
unsigned long long*) _txDumpExceptionObjJmp)
11535 $ longjmp (_txDumpExceptionObjJmp, 1);
11540 #if defined (_MSC_VER)
11541 if (code == EXCEPTION_STACK_OVERFLOW) {$ _resetstkoflw(); }
11544 $
bool primaryException = !(func && exc) || !((unhExc && *_txDumpSE) || _TX_MSC__CXX_DETECT_RETHROW (exc->ExceptionRecord));
11546 $
if (primaryException && exc)
11548 $
unsigned err = GetLastError();
11550 $
const char* stackTrace = _txCaptureStackBackTrace (0,
true, exc->ContextRecord, exc);
11552 $ _txDumpExceptionSEH (_txDumpSE, (intptr_t)
sizeof (_txDumpSE) - 1, exc->ExceptionRecord, func);
11553 $ _tx_snprintf_s (_txTraceSE, (intptr_t)
sizeof (_txTraceSE) - 1,
"%s", stackTrace);
11555 $
static _tx_thread DWORD prevCode = 0;
11556 $
static _tx_thread
void* prevAddr = NULL;
11558 $
if (code != prevCode && addr != prevAddr &&
11559 !strstr (_txDumpSE,
"Объект исключения C++:"))
11561 $ SetLastError (err);
11562 $ _TX_UNEXPECTED (
"\v\b\t" "%s", _txDumpSE + 1);
11568 $ SetLastError (err);
11571 $
if (_txDumpSE[0] ==
'\a' ||
11575 $ _TX_UNEXPECTED (
"\a\t" "%s"
11576 "С помощью функции _set_se_translator() вы можете сами обработать эту ошибку.",
11580 $
return EXCEPTION_CONTINUE_SEARCH;
11585 intptr_t _txDumpExceptionSEH (
char what[], intptr_t size,
const EXCEPTION_RECORD* exc,
const char func[])
11588 $ assert (size >= 0);
11589 assert (exc);
if (!exc) {$
return 0; }
11592 $
unsigned code = exc->ExceptionCode;
11593 $
void* addr = exc->ExceptionAddress;
11594 $
unsigned params = exc->NumberParameters;
11595 $
const ULONG_PTR* info = exc->ExceptionInformation;
11596 $
void*
object = (params >= 2)? (
void*) info[1] : NULL;
11600 #define PRINT_(...) s += _tx_snprintf_s (s, size-2 - (s-what), ##__VA_ARGS__)
11602 $
const char* sCode = NULL;
11603 $
const char* sDescr = NULL;
11605 #define GET_DESCR_(code, descr) case ((unsigned long) (code)): {$ sCode = #code; sDescr = descr; break; }
11609 GET_DESCR_ (EXCEPTION_ACCESS_VIOLATION,
" " "Нарушение доступа к памяти.")
11610 GET_DESCR_ (EXCEPTION_ILLEGAL_INSTRUCTION, " " "Недопустимая операция.")
11611 GET_DESCR_ (EXCEPTION_PRIV_INSTRUCTION, " " "Привилегированная операция.")
11612 GET_DESCR_ (EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "\a" "Выход за границы массива. Ставьте ассерты!")
GET_DESCR_ (EXCEPTION_BREAKPOINT, "\a" "Достигнута точка останова. Удачи в отладке!")
GET_DESCR_ (EXCEPTION_DATATYPE_MISALIGNMENT, "\a" "Нарушение выравнивания данных.")
GET_DESCR_ (EXCEPTION_INVALID_DISPOSITION, "\a" "Обработчик исключения возвратил неверное значение.")
GET_DESCR_ (EXCEPTION_IN_PAGE_ERROR, "\a" "Невозможно загрузить нужную страницу памяти.")
GET_DESCR_ (EXCEPTION_NONCONTINUABLE_EXCEPTION, "\a" "Продолжение выполнения невозможно.")
GET_DESCR_ (EXCEPTION_SINGLE_STEP, "\a" "Выполнена инструкция машинного кода. Одна штука.")
GET_DESCR_ (EXCEPTION_STACK_OVERFLOW, "\a" "Ю-ху! Переполнение стека!")
GET_DESCR_ (EXCEPTION_GUARD_PAGE, "\a" "Попытка доступа к защищенной странице памяти.")
GET_DESCR_ (EXCEPTION_INVALID_HANDLE, "\a" "Неверный или уже закрытый дескриптор.")
GET_DESCR_ (STATUS_POSSIBLE_DEADLOCK, "\a" "Возможно, взаимная блокировка ресурсов.")
GET_DESCR_ (EXCEPTION_FLT_STACK_CHECK, "\a" "Ошибка стека при операции с плавающей точкой.")
GET_DESCR_ (EXCEPTION_FLT_DENORMAL_OPERAND, " " "Денормализация числа с плавающей точкой.")
GET_DESCR_ (EXCEPTION_FLT_DIVIDE_BY_ZERO, " " "Деление на ноль при операции с плавающей точкой.")
GET_DESCR_ (EXCEPTION_FLT_INEXACT_RESULT, " " "Неточный результат при операции с плавающей точкой.")
GET_DESCR_ (EXCEPTION_FLT_INVALID_OPERATION, " " "Недопустимая операция с плавающей точкой.")
GET_DESCR_ (EXCEPTION_FLT_OVERFLOW, " " "Переполнение при операции с плавающей точкой.")
GET_DESCR_ (EXCEPTION_FLT_UNDERFLOW, " " "Потеря значимости при операции с плавающей точкой.")
GET_DESCR_ (STATUS_FLOAT_MULTIPLE_FAULTS, " " "Множественные ошибки с плавающей точкой.")
GET_DESCR_ (EXCEPTION_INT_DIVIDE_BY_ZERO, "\a" "Целочисленное деление на ноль.")
GET_DESCR_ (EXCEPTION_INT_OVERFLOW, "\a" "Переполнение при целочисленной операции.")
GET_DESCR_ (EXCEPTION_CLR_FAILURE, "\a" "Сбой среды исполнения (CLR).")
GET_DESCR_ (STATUS_STACK_BUFFER_OVERRUN, "\a" "Переполнение стекового буфера!")
GET_DESCR_ (STATUS_ASSERTION_FAILURE, "\a" "Сработал assert. На этот раз из ядра.")
GET_DESCR_ (STATUS_WX86_BREAKPOINT, "\a" "Точка останова подсистемы эмуляции x86.")
GET_DESCR_ (RPC_S_UNKNOWN_IF, "\a" "Неизвестный интерфейс удаленного вызова процедур (RPC).")
GET_DESCR_ (RPC_S_SERVER_UNAVAILABLE, "\a" "Сервер удаленного вызова процедур (RPC) недоступен.")
GET_DESCR_ (DBG_TERMINATE_THREAD, "\a" "Отладчик завершил поток сознания.")
GET_DESCR_ (DBG_TERMINATE_PROCESS, "\a" "Отладчик завершил процесс.")
GET_DESCR_ (DBG_CONTROL_C, "\a" "Отладчик получил сигнал прерывания Control+C.")
GET_DESCR_ (DBG_CONTROL_BREAK, "\a" "Отладчик получил сигнал прерывания Control+Break.")
GET_DESCR_ (DBG_THREAD_NAME, " " "Отладчик получил указание дать потоку имя.")
GET_DESCR_ (DBG_PRINTEXCEPTION_C, " " "Отладчик вывел исключение по CTRL+C (OutputDebugStringA).")
GET_DESCR_ (DBG_PRINTEXCEPTION_WIDE_C, " " "Отладчик вывел исключение по CTRL+C (OutputDebugStringW).")
GET_DESCR_ (EXCEPTION_CPP_MSC, " " "Исключение С++, вызванное оператором throw.")
GET_DESCR_ (EXCEPTION_CPP_GCC, " " "Исключение С++, вызванное оператором throw.")
GET_DESCR_ (EXCEPTION_CPP_GCC_UNWIND, " " "Исключение С++, вызванное во время раскрутки стека (rethrow?).")
GET_DESCR_ (EXCEPTION_CPP_GCC_FORCED, " " "Исключение С++, вызванное нарушением магии.")
GET_DESCR_ (EXCEPTION_CPP_BORLAND_BUILDER, "\a" "Это скомпилилось под Билдер? O_O")
GET_DESCR_ (EXCEPTION_CPP_BORLAND_DELPHI, "\a" "Это же С++. Как это вышло?")
default: $ break;
}
#undef GET_DESCR_
$ if (sDescr)
{
$ PRINT_ ("%s\n\n" "#%ld: Исключение %s", sDescr, _txSENumber, sCode);
}
else
{
$ PRINT_ ("\a#%ld: ", _txSENumber);
$ s += FormatMessage (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, //-V102
GetModuleHandle ("NTDLL.DLL"), code, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
s, (DWORD) (size - (s-what)), NULL) - 2; //-V202
$ PRINT_ ("\r\r");
}
$ PRINT_ (" (0x%X) при выполнении кода по адресу", code);
$ PRINT_ ((addr? " 0x%p" : " NULL"), addr);
$ Win32::SYMBOL_INFO* sym = NULL;
$ Win32::IMAGEHLP_LINE64* line = NULL;
if (addr) {$ _txSymGetFromAddr (addr, &sym, &line); }
$ if (sym && *sym->Name) PRINT_ (" в функции %s()", sym->Name);
$ if (line && line->FileName && *line->FileName) PRINT_ (" в файле %s на строке %u", line->FileName, (unsigned) line->LineNumber);
$ if (code == EXCEPTION_ACCESS_VIOLATION ||
code == EXCEPTION_IN_PAGE_ERROR)
{
$ PRINT_ (". Попытка ");
$ unsigned long op = 0xBADC0DE;
$ const char* sOp = "(действие не указано)";
$ if (params >= 1)
{
$ switch (op = (unsigned long) info[0]) //-V202
{
case 0: $ sOp = "прочесть данные"; break;
case 1: $ sOp = "записать данные"; break;
case 8: $ sOp = "исполнить код"; break;
default: $ sOp = "совершить операцию 0x%lX"; break;
}
}
$ PRINT_ (sOp, op);
$ if (params >= 2) {$ PRINT_ ((object? " по адресу 0x%p" : " по адресу NULL"), object); } //-V1048
else {$ PRINT_ (" (адрес не указан)"); }
$ if (code == EXCEPTION_IN_PAGE_ERROR)
{
$ PRINT_ (", ошибка ввода-вывода:");
$ if (params >= 3)
{
$ unsigned long ntstatus = (unsigned long) info[2]; //-V202
$ PRINT_ (" 0x%lX (", ntstatus);
$ s += FormatMessage (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, //-V102
GetModuleHandle ("NTDLL.DLL"), ntstatus, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
s, (DWORD) (size - (s-what)), NULL) - 2; //-V202
$ PRINT_ (")");
}
else
{$ PRINT_ (" (не указана)"); }
}
}
$ HMODULE module = NULL;
$ _TX_CALL (Win32::GetModuleHandleEx, (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const char*) addr, &module));
$ if (module)
{
$ static char sModule [MAX_PATH] = "";
$ int ok = GetModuleFileName (module, sModule, sizeof (sModule));
$ char* ext = (ok? strrchr (sModule, '.') : NULL);
$ if (ext) _strlwr_s (ext, sizeof (sModule) - 1 - (ext - sModule));
if (ok) {$ PRINT_ (" в модуле %s", sModule); }
else {$ PRINT_ (" в модуле 0x%p", (void*) module); }
}
$ PRINT_ (".");
$ if (_txSENumber >= _TX_EXCEPTIONS_LIMIT+0)
{$ PRINT_ (" Дополнительно, превышен лимит исключений _TX_EXCEPTIONS_LIMIT (%d).", _TX_EXCEPTIONS_LIMIT+0); }
$ if (_txSEFatalNumber >= _TX_FATAL_EXCEPTIONS_LIMIT+0)
{$ PRINT_ (" Также превышен лимит фатальных исключений _TX_FATAL_EXCEPTIONS_LIMIT (%d).", _TX_FATAL_EXCEPTIONS_LIMIT+0); }
$ PRINT_ (" Спасибо %s(), что сообщил. Люблю его <3", func);
$ if (exc->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
{$ PRINT_ ("\n\n" "Ой, всё (EXCEPTION_NONCONTINUABLE)."); }
$ if (exc->ExceptionRecord)
{
$ PRINT_ ("\n\n" "Причина:" "\n\n");
$ s += _txDumpExceptionSEH (s, size - (s-what), exc->ExceptionRecord, func);
}
$ if (code == EXCEPTION_CPP_GCC ||
code == EXCEPTION_CPP_GCC_UNWIND ||
code == EXCEPTION_CPP_GCC_FORCED ||
code == EXCEPTION_CPP_MSC)
{
$ s += _txDumpExceptionCPP (s, size - (s-what), code, params, info);
}
#undef PRINT_
$ while (s > what && s[-1] == '\n') s--;
$ if (s > what) s += _tx_snprintf_s (s, size - (s-what), "\n\n");
$ return s - what;
}
//-----------------------------------------------------------------------------------------------------------------
intptr_t _txDumpExceptionCPP (char what[], intptr_t size,
unsigned code /*= 0*/, unsigned params /*= 0*/, const ULONG_PTR info[] /*= NULL*/)
{
$6 assert (what);
$ assert (size >= 0); //-V547
$ char* s = what;
$ switch (code)
{
#if defined (_GCC_VER)
case EXCEPTION_CPP_GCC:
case EXCEPTION_CPP_GCC_UNWIND:
case EXCEPTION_CPP_GCC_FORCED:
{
// See: [1] http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_exception.cpp
// [2] http://github.com/gcc-mirror/gcc/blob/master/libgcc/unwind-seh.c, lines 51-55 and below
// [3] http://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_throw.cc, __cxa_throw, line 59 and below
// [4] http://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/unwind-cxx.h, __cxa_exception, line 58 and below
// and figure above near ABI::__cxa_exception definition in this file
$ const std::type_info* type = NULL;
$ void* object = NULL;
$ if (params >= 1)
{
$ _Unwind_Exception* unwind_exception = (_Unwind_Exception*) info[0];
$ ABI::__cxa_exception* cxa_exception = (ABI::__cxa_exception*) (unwind_exception + 1) - 1;
$ type = cxa_exception->exceptionType;
$ object = cxa_exception + 1;
}
$ s += _txDumpExceptionObj (s, size - (s-what), object, 0, type);
}
$ break;
case 0: // Not called within SEH chain
{
// From: [1] http://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_type.cc
// [2] http://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/vterminate.cc
using namespace abi;
$ ABI::__cxa_exception* cxa_exception = __cxa_get_globals() -> caughtExceptions;
$ if (cxa_exception && (cxa_exception->unwindHeader.exception_class & 1)) // Dependent exception, case B, see pic above
{
$ cxa_exception = (((ABI::__cxa_exception*) (&cxa_exception->unwindHeader + 1) - 1) -> primaryException) - 1;
}
$ if (cxa_exception)
{
$ verify (cxa_exception->exceptionType == abi::__cxa_current_exception_type());
$ s += _txDumpExceptionObj (s, size, cxa_exception + 1, 0, cxa_exception->exceptionType);
}
}
$ break;
#elif defined (_MSC_VER)
case EXCEPTION_CPP_MSC:
{
// See [1] http://blogs.msdn.microsoft.com/oldnewthing/20100730-00/?p=13273
// [2] http://www.openrce.org/articles/full_view/21
// [3] http://www.openrce.org/articles/full_view/23
// [4] http://yurichev.com/mirrors/RE/Recon-2012-Skochinsky-Compiler-Internals.pdf
$ const std::type_info* type = NULL;
$ void* object = (params >= 2)? (void*) info[1] : NULL;
$ size_t szObj = 0;
$ if (params >= 3 &&
(info[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER1 ||
info[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER2 ||
info[0] == EXCEPTION_CPP_MSC_EH_MAGIC_NUMBER3 ||
info[0] == EXCEPTION_CPP_MSC_EH_PURE_MAGIC_NUMBER1))
{
$ auto throwInfo = (const Win32::ThrowInfo*) info[2];
$ if (throwInfo && throwInfo->pCatchableTypeArray)
{
$ HMODULE module = (params >= 4)? (HMODULE) info[3] : NULL; //-V112
#define RVA_(type, addr) ( (type) ((uintptr_t) module + (uintptr_t) (addr)) )
$ const Win32::CatchableTypeArray* cArray = RVA_(const Win32::CatchableTypeArray*, throwInfo->pCatchableTypeArray);
$ const Win32::CatchableType* cType = RVA_(const Win32::CatchableType*, cArray->arrayOfCatchableTypes[0]);
$ type = RVA_(const std::type_info*, cType->pType);
$ szObj = cType->sizeOrOffset; //-V101
#undef RVA_
}
}
$ s += _txDumpExceptionObj (s, size - (s-what), object, szObj, type);
}
break;
case 0: // Not called within SEH chain
// signal() handlers or unexpected()/terminate() are called after Vectored Exception in MSC:
//
// terminate() is called by __scrt_unhandled_exception_filter() in case of MSC exception.
// See C:\Bin\Microsoft Visual Studio 14.0\VC\crt\src\vcruntime\utility_desktop.cpp
//
// signal() handlers are called by _seh_filter_exe(), which is called by _mainCRTStartup() in case of exception.
// See C:\Bin\Microsoft Visual Studio 14.0\VC\crt\src\vcruntime\mcrtexe.cpp
// and C:\Bin\Windows Kits\10\Source\10.0.10240.0\ucrt\misc\exception_filter.cpp
// and http://msdn.microsoft.com/en-us/library/ff730818.aspx.
//
// So _txDumpSE information should have been recorded during previous call. Now do nothing.
$ break;
#endif
default:
$ txOutputDebugPrintf ("ERROR: Wrong call to %s: Unknown exception code 0x%08X\n", __TX_FUNCTION__, code);
$ break;
}
$ while (s > what && s[-1] == '\n') s--;
$ if (s > what) s += _tx_snprintf_s (s, size - (s - what), "\n\n");
$ return (s - what);
}
//-----------------------------------------------------------------------------------------------------------------
intptr_t _txDumpExceptionObj (char what[], intptr_t size, void* object, size_t sizeObj, const std::type_info* type) //-V2008
{
$6 assert (what);
$ assert (size > 0); //-V547
$ static char* s = NULL; s = what;
$ static size_t szObj = 0; szObj = sizeObj;
#define PRINT_(...) s += _tx_snprintf_s (s, size - (s - what), ##__VA_ARGS__)
$ PRINT_ ("\n\n" "Объект исключения C++:");
$ const char* mangledName = (type)? type->name() : NULL;
$ char* typeName = NULL;
$ int err = 1;
#if defined (_GCC_VER)
$ typeName = ::abi::__cxa_demangle (mangledName, 0, 0, &err);
#endif
$ const char* name = (!err && typeName)? typeName : mangledName; //-V560
$ if (name &&
(strcmp (name, "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >") == 0 ||
strcmp (name, "std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >") == 0))
{$ name = "std::string"; }
$ if (name &&
(strcmp (name, "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *") == 0 ||
strcmp (name, "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > * __ptr64") == 0 ||
strcmp (name, "std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*") == 0))
{$ name = "std::string*"; }
if (name) {$ PRINT_ (" %s", name); }
#if defined (_GCC_VER)
$ free (typeName);
#endif
$ err = 0;
$ if (mangledName)
{
if (_txSetJmp())
{
#define PRINT_VAL_(fmt, typ, ...) \
else if (*type == typeid ( typ )) {$ PRINT_ (" = " #fmt, (* (typ* ) object) __VA_ARGS__); } \
else if (*type == typeid (const typ )) {$ PRINT_ (" = " #fmt, (* (typ* ) object) __VA_ARGS__); } \
else if (*type == typeid ( typ* )) {$ PRINT_ (" = " #fmt, (**(typ**) object) __VA_ARGS__); } \
else if (*type == typeid (const typ* )) {$ PRINT_ (" = " #fmt, (**(typ**) object) __VA_ARGS__); } \
else if (*type == typeid ( typ* const)) {$ PRINT_ (" = " #fmt, (**(typ**) object) __VA_ARGS__); } \
else if (*type == typeid (const typ* const)) {$ PRINT_ (" = " #fmt, (**(typ**) object) __VA_ARGS__); }
#define NO_
if (false) ;
PRINT_VAL_ ("%s", char*, NO_) PRINT_VAL_ ('%c', unsigned char, NO_) PRINT_VAL_ (%s, bool, ? "true" : "false") //-V206 //-V517
PRINT_VAL_ ( %d, int, NO_) PRINT_VAL_ ( %u, unsigned int, NO_) PRINT_VAL_ (%g, float, NO_) //-V206
PRINT_VAL_ ( %hd, short, NO_) PRINT_VAL_ ( %hu, unsigned short, NO_) PRINT_VAL_ (%g, double, NO_) //-V206
PRINT_VAL_ ( %ld, long, NO_) PRINT_VAL_ ( %lu, unsigned long, NO_) PRINT_VAL_ ('%c', char, NO_) //-V206
PRINT_VAL_ ("%s", std::string, .c_str()) //-V206
else if (std::exception* e = dynamic_cast <std::exception*> ( (std::exception* ) object))
{
$ PRINT_ (", what(): \"%s\"", e->what());
}
else
{$ err = 1; }
}
else
{$ err = 2; }
}
$ _txClearJmp();
$ if (err && object && szObj)
{
$ const unsigned char* buf = (const unsigned char*) object;
$ if (szObj >= 64) szObj = 64;
$ PRINT_ (", дамп: [");
$ for (size_t i = 0; i < szObj; i++) PRINT_ ("%c", (isprint (buf[i]) && !iscntrl (buf[i]))? buf[i] : '.' );
$ PRINT_ ("]");
$ for (size_t i = 0; i < szObj; i++) PRINT_ (" %02X", buf[i]);
$ err = 0;
}
$ if (err)
{$ PRINT_ (" = ??"); }
$ PRINT_ ((object? "%sего адрес 0x%p." : "%sего адрес NULL."), ((typeName || mangledName)? ", " : ""), object); //-V560
#undef PRINT_VAL_
#undef PRINT_
#undef NO_
$ return s - what;
}
#endif // TX_COMPILED
//}
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//{ Stack trace and debug info access
//-----------------------------------------------------------------------------------------------------------------
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
const char* _txCaptureStackBackTrace (int framesToSkip /*= 0*/, bool readSource /*= true*/,
CONTEXT* context /*= NULL*/, EXCEPTION_POINTERS* exc /*= NULL*/,
HANDLE thread /*= GetCurrentThread()*/)
{
$6 const int maxFrames = 62; // MS says: < 63
$ static char trace [(MAX_PATH + 1024+1) * maxFrames] = "";
if (framesToSkip == -1) {$ return trace; }
$ static void* capture [maxFrames] = {};
$ int frames = _txStackWalk (framesToSkip + !context, sizearr (capture), capture, context, thread);
$ memset (trace, 0, sizeof (trace));
$ char* s = trace;
#define PRINT_(...) s += _tx_snprintf_s (s, sizeof (trace) - 1 - 3 - (s-trace), ##__VA_ARGS__)
$ for (int i = 0, n = 0; i < frames; i++) //-V2530
{
$ void* addr = capture[i];
$ Win32::SYMBOL_INFO* sym = NULL;
$ Win32::IMAGEHLP_LINE64* line = NULL;
$ const char* module = NULL;
$ const char* source = NULL;
$ bool inTX = false;
if (addr) {$ inTX = _txSymGetFromAddr ((char*) addr - 1, &sym, &line, &module); }
if (readSource && !inTX) {$ _txSymGetFromAddr ((void*) 1, NULL, NULL, NULL, &source, 2); } //-V566
$ int nl = 0;
$ while (s > trace && s[-1] == '\n') { s--; nl++; }
#if !defined (_TX_FULL_STACKTRACE)
$ if (! ((sym && *sym->Name) || (line && ((line->FileName && *line->FileName) || line->LineNumber))))
{$ continue; }
#endif
$ PRINT_ ("%s#%2d 0x%p", ((n)? ((source || nl)? "\n\n" : "\n") : ""), i, addr);
$ n++;
if (addr == 0) {$ PRINT_ (" [Неверный фрейм]"); break; }
if (addr == (void*) -1) {$ PRINT_ (" [Странный фрейм]"); break; }
if (addr == (void*)(uintptr_t) 0xBAADF00D) {$ PRINT_ (" [Мусор от LocalAlloc()]"); break; } //-V566
if (module) {$ PRINT_ (" in %s%s", module, ((sym && *sym->Name)? ": " : "")); }
if (sym && *sym->Name) {$ PRINT_ ("%s()", sym->Name); }
if (line && line->FileName) {$ PRINT_ (" at %s", line->FileName); }
if (line && line->LineNumber) {$ PRINT_ (" (%d)", (int) line->LineNumber); }
if (source) {$ PRINT_ (":\n\n" "%s\n", source); }
if (sym && strcmp (sym->Name , "main") == 0) {$ break; }
}
#if defined (_MSC_VER)
#pragma warning (push)
#pragma warning (disable: 28199) // Using possibly uninitialized memory '*s'
#endif
$ while (s > trace && s[-1] == '\n') s--;
$ *s = 0;
#if defined (_MSC_VER)
#pragma warning (pop) // Using possibly uninitialized memory '*s'
#endif
#undef PRINT_
$ s += _tx_snprintf_s (s, sizeof (trace) - 1 - (s-trace), "");
#if !defined (_TX_NO_MINIDUMP)
$ _txCreateMiniDump (exc);
#endif
$ return trace;
}
//-----------------------------------------------------------------------------------------------------------------
// Stack WALKING if the program is DEAD. Dead, Carl!
int _txStackWalk (int framesToSkip, size_t szCapture, void* capture[], CONTEXT* context /*= NULL*/,
HANDLE thread /* = GetCurrentThread()*/)
{
$6 namespace MinGW = Win32::MinGW;
$ assert (capture);
$ HANDLE process = GetCurrentProcess();
$ bool thisThread = !Win32::GetThreadId || (Win32::GetThreadId (thread) == GetCurrentThreadId());
$ CONTEXT ctx = {};
$ ctx.ContextFlags |= CONTEXT_FULL;
$ int isWow64 = 0;
$ if (Win32::IsWow64Process) Win32::IsWow64Process (process, &isWow64);
else {$ return -1; }
$ if (context)
{
$ ctx = *context;
}
else
{
$ if (thisThread)
{
$ _TX_CALLv (Win32::RtlCaptureContext, (&ctx));
}
else
{
$ SuspendThread (thread); //-V720
$ ctx.ContextFlags = CONTEXT_ALL;
$ bool ok = !!GetThreadContext (thread, &ctx);
$ if (!ok)
{
$ ResumeThread (thread);
$ return -1;
}
}
}
$ Win32::STACKFRAME64 frame = {};
$ frame.AddrPC.Mode = frame.AddrStack.Mode = frame.AddrFrame.Mode = Win32::AddrModeFlat;
$ int cpu = 0;
#if defined (_WIN64)
$ if (isWow64)
{
$ Win32::WOW64_CONTEXT wow64ctx = {};
$ wow64ctx.ContextFlags |= WOW64_CONTEXT_FULL;
$ if (!_TX_CALL (Win32::Wow64GetThreadContext, (thread, &wow64ctx))) // This call fails in WINE,
{ // while EXIT_PROCESS_DEBUG_EVENT
if (!thisThread) {$ ResumeThread (thread); }
$ return 0;
}
$ cpu = IMAGE_FILE_MACHINE_I386;
$ frame.AddrPC .Offset = wow64ctx.Eip;
$ frame.AddrStack.Offset = wow64ctx.Esp;
$ frame.AddrFrame.Offset = wow64ctx.Ebp;
}
else
{
$ cpu = IMAGE_FILE_MACHINE_AMD64;
$ frame.AddrPC .Offset = ctx.Rip;
$ frame.AddrStack.Offset = ctx.Rbp;
$ frame.AddrFrame.Offset = ctx.Rsp;
}
#else
{
$ cpu = IMAGE_FILE_MACHINE_I386;
$ frame.AddrPC .Offset = ctx.Eip;
$ frame.AddrStack.Offset = ctx.Ebp;
$ frame.AddrFrame.Offset = ctx.Esp;
}
#endif
$ assert (cpu);
if (_txSetJmp())
{
$ _txSymGetFromAddr ((void*) 1); //-V566
}
$ _txClearJmp();
$ int frames = -1;
$ for (frames = -framesToSkip; frames < (int) szCapture; frames++) //-V202 //-V2530
{
$ DWORD64 prev = frame.AddrStack.Offset;
// Я злой и страшный серый walk. Я в поросятах знаю talk.
if (!_txSetJmp()) {$ break; }
#if defined (_GCC_VER)
if (!_TX_CALL (MinGW::StackWalk64, (cpu, process, thread, &frame, &ctx, NULL,
MinGW::SymFunctionTableAccess64, MinGW::SymGetModuleBase64, NULL))) {$ break; }
#elif defined (_MSC_VER)
$ if (!_TX_CALL (Win32::StackWalk64, (cpu, process, thread, &frame, &ctx, NULL,
Win32::SymFunctionTableAccess64, Win32::SymGetModuleBase64, NULL))) {$ break; }
#else
#error _GCC_VER / _MSC_VER not defined
#endif
if (frames < 0) {$ continue; }
$ void* addr = (void*) frame.AddrPC.Offset;
if (frame.AddrFrame.Offset == 0) {$ addr = 0; } // Bad frame
if (frame.AddrStack.Offset < prev) {$ addr = (void*) -1; } // Strange frame
$ assert (0 <= frames && frames < (int) szCapture); //-V202
$ capture[frames] = addr; //-V108
}
$ _txClearJmp();
if (!thisThread) {$ ResumeThread (thread); }
$ return frames;
}
// Note that Rick and Carl are speaking near the C language block. "C block", Carl. See: http://knowyourmeme.com/memes/carl
//-----------------------------------------------------------------------------------------------------------------
bool _txSymGetFromAddr (void* addr, Win32::SYMBOL_INFO** symbol /*= NULL*/,
Win32::IMAGEHLP_LINE64** line /*= NULL*/, const char** module /*= NULL*/,
const char** source /*= NULL*/, int context /*= 2*/)
{
$7 static HANDLE process = NULL;
#if defined (_GCC_VER)
#define LIB_ Win32::MinGW
#elif defined (_MSC_VER)
#define LIB_ Win32
#else
#error _GCC_VER / _MSC_VER not defined
#endif
$ if (!process && addr)
{
$ process = GetCurrentProcess();
$ DWORD options = SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_LOAD_ANYTHING | SYMOPT_INCLUDE_32BIT_MODULES |
SYMOPT_DEFERRED_LOADS | SYMOPT_FAVOR_COMPRESSED | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_NO_PROMPTS;
$ _TX_CALL (LIB_::SymSetOptions, (options));
$ _TX_CALL (LIB_::SymInitialize, (process, NULL, true));
}
$ static DWORD64 mod = 0;
$ if (module)
{
$ static char sMod [MAX_PATH] = "";
$ memset (sMod, 0, sizeof (sMod));
$ mod = _TX_CALL (LIB_::SymGetModuleBase64, (process, (uintptr_t) addr));
$ GetModuleFileName ((HMODULE)(intptr_t) mod, sMod, MAX_PATH);
$ char* ext = strrchr (sMod, '.');
if (ext) {$ _strlwr_s (ext, sizeof (sMod) - (ext-sMod)); }
$ *module = sMod;
}
$ static char buffer [_TX_BUFSIZE] = "";
$ static Win32::SYMBOL_INFO* sym = (Win32::SYMBOL_INFO*) buffer; //-V1032
$ if (symbol)
{
$ memset (buffer, 0, sizeof (buffer));
$ sym->MaxNameLen = sizeof (buffer) - sizeof (Win32::SYMBOL_INFO) - 1;
$ sym->SizeOfStruct = sizeof (Win32::SYMBOL_INFO);
$ unsigned long long ofs = 0;
$ _TX_CALL (LIB_::SymFromAddr, (process, (uintptr_t) addr, &ofs, sym));
if (strcmp (sym->Name, "??") == 0) {$ *sym->Name = 0; }
$ *symbol = sym;
}
$ static Win32::IMAGEHLP_LINE64 line64 = { sizeof (line) };
$ if (line)
{
$ memset (&line64, 0, sizeof (line64));
$ DWORD ofs = 0;
$ _TX_CALL (LIB_::SymGetLineFromAddr64, (process, (uintptr_t) addr, &ofs, &line64));
$ *line = &line64;
}
$ if (source)
{
$ static char buf [_TX_BUFSIZE] = "";
$ memset (buf, 0, sizeof (buf));
$ if (line64.FileName && line64.LineNumber)
{
$ _txReadSource (buf, sizeof (buf) - 1, line64.FileName,
(int) line64.LineNumber - context, (int) line64.LineNumber + context, (int) line64.LineNumber);
$ *source = buf;
}
if (!*source || !**source) {$ *source = NULL; }
}
$ if (!addr && process)
{
$ _TX_CALL (LIB_::SymCleanup, (process));
$ process = NULL;
}
#if (_GCC_VER == 481)
#pragma GCC diagnostic push
#pragma GCC system_header
#endif
$ if (symbol)
{
$ if (strstr (sym->Name, "::TX::") ||
(strncmp (sym->Name, "_tx", 3) == 0 && isupper ((unsigned char) sym->Name[3])) ||
(strncmp (sym->Name, "tx", 2) == 0 && isupper ((unsigned char) sym->Name[2])) ||
strncmp (sym->Name, "_tx_", 4) == 0 || //-V112
strncmp (sym->Name, "tx_", 3) == 0)
{
$ return true;
}
#if (_GCC_VER == 481)
#pragma GCC diagnostic pop
#endif
$ if (!line || !line64.FileName) return false;
$ intptr_t len = strlen (line64.FileName) - (sizeof (__FILE__) - 1);
$ return (len >= 0 && _stricmp (line64.FileName + len, __FILE__) == 0) &&
(len == 0 || line64.FileName[len-1] == '/' || line64.FileName[len-1] == '\\');
}
#undef LIB_
$ return false;
}
//-----------------------------------------------------------------------------------------------------------------
intptr_t _txReadSource (char buf[], intptr_t size, const char file[],
int linStart /*= 0*/, int linEnd /*= INT_MIN*/, int linMark /*= INT_MIN*/)
{
$7 assert (buf);
if (!file || !*file) {$ return 0; }
if (linStart < 1) {$ linStart = 1; }
if (linEnd == -1) {$ linEnd = INT_MAX; }
$ FILE* f = NULL;
$ fopen_s (&f, file, "r");
if (!f) {$ return 0; }
$ int n = 1;
while (!feof (f))
{
if (n >= linStart) {$ break; }
while (!feof (f) && fgetc (f) != '\n')
;
n++;
}
$ char* s = buf;
#define SZ_ ( size - 3 - (s - buf) )
$ while (!feof (f) && SZ_ > 0)
{
if (n > linEnd || _txNOP (SZ_) < 0) {$ break; }
if (linMark != INT_MIN)
{$ s += _tx_snprintf_s (s, SZ_, "%s%5d: ", ((n == linMark)? "=>" : " "), n); }
$ int c = 0;
$ while (!feof (f) && SZ_ > 0 && (c = fgetc (f)) != '\n') *s++ = (char) c;
if (c == EOF) {$ s--; }
if (SZ_ > 0) {$ *s++ = '\n'; }
$ n++;
}
if (n <= linEnd && SZ_ <= 0)
{$ s += _tx_snprintf_s (s, size - (s - buf), "..."); }
#undef SZ_
$ fclose (f);
if (s > buf && s[-1] == '\n') {$ s--; }
$ *s = 0;
$ return (s - buf);
}
//-----------------------------------------------------------------------------------------------------------------
const char* _txCaptureStackBackTraceTX (int framesToSkip /*= 0*/, bool readSource /*= false*/)
{
$6 const int maxFrames = 62; // TX says too: < 63
$ static char trace [(MAX_PATH + 1024+1) * maxFrames] = "";
if (framesToSkip == -1) {$ return trace; }
$ memset (trace, 0, sizeof (trace));
$ char* s = trace;
#define SZ_ ( sizeof (trace) - 1 - 3 - (s-trace) )
$ const _txLoc* loc = &_txLoc::Cur;
for (int i = 0; loc && i < framesToSkip + 1; i++, loc = loc->prev) { $; }
$ for (int i = -framesToSkip; loc && i < maxFrames; i++, loc = loc->prev)
{
if (i < 0) {$ continue; }
if (loc->func || loc->file || loc->line)
{
$ s += _tx_snprintf_s (s, SZ_, "%s#%2d in %s at %s:%d", (i? readSource? "\n\n" : "\n" : ""),
i, loc->func, loc->file, loc->line);
$ if (readSource)
{
$ s += _tx_snprintf_s (s, SZ_, ":\n\n");
$ s += _txReadSource (s, SZ_, loc->file, loc->line - 2, loc->line + 2, loc->line);
}
}
}
#undef SZ_
$ s += _tx_snprintf_s (s, sizeof (trace) - 1 - (s-trace), "");
$ return trace;
}
//-----------------------------------------------------------------------------------------------------------------
bool _txCreateMiniDump (EXCEPTION_POINTERS* exc /*= NULL*/)
{
$6 static char dumpName[MAX_PATH] = "";
if (!*dumpName) {$ _tx_snprintf_s (dumpName, sizeof (dumpName) - 1, "%s.dmp", _txLogName); }
$ HANDLE file = CreateFile (dumpName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (!file || file == INVALID_HANDLE_VALUE) {$ return false; }
$ Win32::MINIDUMP_EXCEPTION_INFORMATION excInfo = { GetCurrentThreadId(), exc, false };
$ Win32::MINIDUMP_TYPE type = (Win32::MINIDUMP_TYPE) (Win32::MiniDumpWithIndirectlyReferencedMemory | Win32::MiniDumpScanMemory);
$ bool ok = _TX_CALL (Win32::MiniDumpWriteDump, (GetCurrentProcess(), GetCurrentProcessId(), file, type,
((exc)? &excInfo : NULL), NULL, NULL));
$ CloseHandle (file);
if (ok) {$ return true; }
else {$ return false; }
}
#endif // TX_COMPILED
//}
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//{ Errors reporting
//-----------------------------------------------------------------------------------------------------------------
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
const char* _txProcessError (const char file[], int line, const char func[], unsigned color, const char msg[], va_list args) //-V2008
{
_txErrors = _txErrors + 1;
DWORD winErr = GetLastError();
int crtErr = errno;
#if !defined (__CYGWIN__)
unsigned long dosErr = _doserrno;
#else
unsigned long dosErr = 0;
#endif
unsigned dlgErr = _TX_CALL (Win32::CommDlgExtendedError, ());
unsigned oglErr = _TX_CALL (Win32::wglGetCurrentDC, ())? _TX_CALL (Win32::glGetError, ()) : _txOGLError;
unsigned threadId = GetCurrentThreadId();
enum { isFatal = 0x01, isWarning = 0x02, noMsgBox = 0x04, fmtOnly = 0x08, traceSE = 0x10 };
unsigned options = 0;
for (; msg && *msg; msg++)
{
if (*msg == '\a') options |= isFatal;
else if (*msg == '\v') options |= isWarning;
else if (*msg == '\b') options |= noMsgBox;
else if (*msg == '\f') options |= fmtOnly;
else if (*msg == '\t') options |= traceSE;
else break;
}
const char* stkTrace = NULL;
const char* txTrace = NULL; (void) txTrace;
if (!(options & fmtOnly))
{
stkTrace = ((options & traceSE) && *_txTraceSE)? _txTraceSE : _txCaptureStackBackTrace (2, true);
txTrace = _txCaptureStackBackTraceTX (0, true);
}
static char what[_TX_BIGBUFSIZE*10] = "";
static char str [_TX_BIGBUFSIZE] = "";
char *s = what;
#define PRINT_(...) s += _tx_snprintf_s (s, sizeof (what) - 1 - (s - what), ##__VA_ARGS__)
#define VPRINT_(...) s += _tx_vsnprintf_s (s, sizeof (what) - 1 - (s - what), ##__VA_ARGS__)
PRINT_ ("TXLib %s\n\n", ((options & isWarning)? "предупреждает:" :
(options & isFatal)? "соболезнует..." :
"сообщает:"));
PRINT_ ("Программа: %s", txGetModuleFileName());
if (file) PRINT_ (", файл: %s", file);
if (line) PRINT_ (", строка: %d", line);
if (func) PRINT_ (", функция: %s", func);
PRINT_ (",\n\n");
if (msg) PRINT_ ("%s: ", (file || line || func)? "Сообщение" : "ВНЕЗАПНО"),
VPRINT_ (msg, args);
while (s > what && s[-1] == '\n') s--;
PRINT_ ("\n\n" "#%d: %s, Instance: 0x%p (%d-bit), Flags: %c%c%c%c%c%d, Thread: 0x%X%s",
_txErrors, _TX_VERSION, (void*) &_txInitialized, (sizeof (void*) == 4)? 32 : 64,
"cC"[!!_txConsole], "mM"[_txMain], "dD"[_txIsDll], "rR"[_txRunning], "eE"[_txExit], _txLoc::Cur.trace,
threadId, (threadId == _txMainThreadId)? " (Main)" :
(threadId == _txCanvas_ThreadId)? " (Canvas)" : "");
if (winErr) PRINT_ (", GetLastError(): %lu (", (unsigned long) winErr),
s += FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, //-V102
NULL, winErr, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
s, (DWORD) (sizeof (what) - (s-what)), NULL) - 2, //-V202
s -= (s[-1] == '.')? 1 : 0,
PRINT_ (")");
if (crtErr) PRINT_ (", errno: %d (%s)", crtErr, (strerror_s (str, sizeof (str), crtErr), str));
if (dosErr) PRINT_ (", _doserrno: %lu (%s)", dosErr, (strerror_s (str, sizeof (str), dosErr), str));
if (oglErr) PRINT_ (", glGetError(): %u (0x%04X, %s)", oglErr, oglErr, _TX_CALL (Win32::gluErrorString, (oglErr)));
if (dlgErr) PRINT_ (", CommDlgExtendedError(): %u (0x%04X)", dlgErr, dlgErr);
#if (__cplusplus >= 201703L) || (defined (_MSVC_LANG) && _MSVC_LANG >= 201703L)
PRINT_ (". %s\n", ::std::uncaught_exceptions()? "std::uncaught_exceptions(): true." : "");
#else
PRINT_ (". %s\n", ::std::uncaught_exception ()? "std::uncaught_exception(): true." : "");
#endif
if (_txLoc::Cur.inTX > 0 && file && !(_txLoc::Cur.line == line && _stricmp (_txLoc::Cur.file, file) == 0) &&
(_txLoc::Cur.file || _txLoc::Cur.line || _txLoc::Cur.func))
PRINT_ ("From: %s:%d %s.\n", _txLoc::Cur.file, _txLoc::Cur.line, _txLoc::Cur.func);
txOutputDebugPrintf ("\r" "%s - ERROR: %s\n", _TX_VERSION, what);
if (options & fmtOnly)
{
SetLastError (winErr);
errno = crtErr;
#if !defined (__CYGWIN__)
_doserrno = dosErr;
#endif
return what;
}
txSetProgress (-1, Win32::TBPF_ERROR);
unsigned restore = txGetConsoleAttr();
txSetConsoleAttr ((options & isFatal)? FOREGROUND_LIGHTMAGENTA : FOREGROUND_LIGHTRED);
if (color) {$ txSetConsoleAttr (color); }
int oldCodePage = txSetLocale();
fprintf (stderr, "\n" "--------------------------------------------------\n"
"%s\n"
"--------------------------------------------------\n",
what);
if (stkTrace && strstr (stkTrace, ".exe: "))
{$ fprintf (stderr, "Стек вызовов:\n\n"
"%s\n\n"
"--------------------------------------------------\n",
stkTrace); }
SetConsoleOutputCP (oldCodePage);
txSetConsoleAttr (restore);
if (*_txLogName) do //-V2530
{
FILE* log = NULL; fopen_s (&log, _txLogName, "a");
if (!log) {$ break; }
fprintf (log, "\n" "--------------------------------------------------\n"
"%s\n"
"--------------------------------------------------\n",
what);
fprintf (log, "Стек вызовов:\n\n" //-V576
"%s\n",
(*_txTraceSE)? _txTraceSE : stkTrace);
#if defined (_TX_ALLOW_TRACE) || defined (_DEBUG)
if (_txLoc::Cur.inTX > 0 && txTrace && *txTrace)
{
fprintf (log, "\n" "--------------------------------------------------\n"
"Стек вызовов TX:\n\n"
"%s\n",
txTrace);
}
#endif
fprintf (log, "\n" "--------------------------------------------------\n"
"%s\n\n"
"--------------------------------------------------\n",
_txAppInfo());
fclose (log);
break;
}
while (false);
txSleep();
int ret = 0;
if (!(options & noMsgBox))
{
txSleep (_txWindowUpdateInterval);
PRINT_ ("\n" "Прервать программу?");
ret = txMessageBox (what, ((options & isWarning)? "Предупреждение" :
(options & isFatal)? "Фатальная ошибка" :
"Ошибка в программе"), MB_ICONSTOP | MB_SYSTEMMODAL | MB_YESNOCANCEL);
}
SetLastError (winErr);
errno = crtErr;
#if !defined (__CYGWIN__)
_doserrno = dosErr;
#endif
if (((options & isFatal) && !IsDebuggerPresent()) || ret == IDYES)
{
txUnlock();
_txCleanup();
Win32::TerminateProcess (GetCurrentProcess(), EXIT_FAILURE);
}
#undef PRINT_
#undef VPRINT_
return what;
}
//-----------------------------------------------------------------------------------------------------------------
#if defined (_MSC_VER)
int _txOnErrorReport (int type, const char* text, int* ret)
{
assert (text);
assert (ret);
_txErrors = _txErrors + 1;
unsigned restore = txGetConsoleAttr();
switch (type)
{
case _CRT_WARN: txSetConsoleAttr (FOREGROUND_LIGHTRED); break;
case _CRT_ERROR: txSetConsoleAttr (FOREGROUND_LIGHTMAGENTA); break;
case _CRT_ASSERT: txSetConsoleAttr (FOREGROUND_YELLOW); break;
default: break; //-V2522
}
const char startReport[] = "Detected memory leaks!\n",
endReport[] = "Object dump complete.\n";
if (strcmp (text, startReport) == 0) // Dirty, dirty hack. А что делать?
{
_txOnErrorReport (type, "\n", NULL);
_txOnErrorReport (type, _TX_VERSION " - ERROR: ", NULL);
_txOnErrorReport (type, "Внимание: Обнаружены утечки памяти! (Для поиска используйте _TX_ALLOC_BREAK.)\n", NULL);
_txOnErrorReport (type, "\n", NULL);
}
size_t len = strlen (text);
if (text [len-1] != '\n') txOutputDebugPrintf ("%s", text);
else if (strcmp (text, endReport) != 0) txOutputDebugPrintf ("%s" "%s - ERROR: ", text, _TX_VERSION);
else txOutputDebugPrintf ("%s\n", text);
DWORD n = 0;
HANDLE err = GetStdHandle (STD_ERROR_HANDLE);
WriteFile (err, text, (DWORD) strlen (text), &n, NULL); //-V202
txSetConsoleAttr (restore);
if (*_txLogName) do //-V2530
{
HANDLE log = CreateFile (_txLogName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (log == INVALID_HANDLE_VALUE) break;
SetFilePointer (log, 0, NULL, FILE_END);
WriteFile (log, text, (DWORD) strlen (text), &n, NULL); //-V202
CloseHandle (log);
break;
}
while (false);
if (ret) *ret = 0;
return (type == _CRT_WARN);
}
#endif
//-----------------------------------------------------------------------------------------------------------------
int txMessageBox (const char text[], const char header[], unsigned flags /*= MB_ICONINFORMATION | MB_OKCANCEL*/)
{
$5 static wchar_t textW [_TX_BIGBUFSIZE * sizeof (wchar_t)] = L"[NULL text]";
$ static wchar_t headerW [_TX_BUFSIZE * sizeof (wchar_t)] = L"[NULL header]";
if (text) {$ MultiByteToWideChar (_TX_CODEPAGE, 0, text, -1, textW, sizearr (textW)) || memset (textW, 0, sizeof (textW)); }
if (header) {$ MultiByteToWideChar (_TX_CODEPAGE, 0, header, -1, headerW, sizearr (headerW)) || memset (headerW, 0, sizeof (headerW)); }
$ txSleep();
$ HWND wnd = _txCanvas_Window;
$ int ret = MessageBoxW ((wnd && IsWindowVisible (wnd))? wnd : _TX_CALL (Win32::GetConsoleWindow,()),
textW, headerW, flags | MB_SETFOREGROUND | MB_TOPMOST);
$ GetAsyncKeyState (VK_SHIFT); GetAsyncKeyState (VK_CONTROL); GetAsyncKeyState (VK_MENU);
$ if (ret == IDCANCEL && GetAsyncKeyState (VK_SHIFT) && GetAsyncKeyState (VK_CONTROL) && GetAsyncKeyState (VK_MENU))
{
$ SendNotifyMessage (txWindow(), (_txMain? WM_CLOSE : WM_DESTROY), 0, 0);
$ _txWaitFor (!_txCanvas_Window, _TX_TIMEOUT);
}
$ return ret;
}
//-----------------------------------------------------------------------------------------------------------------
bool txGetAsyncKeyState (int key)
{
$1 HWND wnd = GetForegroundWindow();
return (GetAsyncKeyState (key) & 0x8000) &&
(wnd == txWindow() || wnd == Win32::GetConsoleWindow());
}
//-----------------------------------------------------------------------------------------------------------------
bool txNotifyIcon (unsigned flags, const char* title, const char* format, ...)
{
$5 if (_TX_ARGUMENT_FAILED (format)) return false;
$ va_list arg; va_start (arg, format);
$ bool ok = true;
#if defined (_WIN32_IE) && (_WIN32_IE >= 0x0500)
$ NOTIFYICONDATA nid = { sizeof (nid) };
$ nid.uFlags = NIF_ICON | NIF_TIP | NIF_INFO;
$ nid.hWnd = NULL;
$ nid.uID = 1;
$ nid.hIcon = _txCreateTXIcon (16); assert (nid.hIcon);
$ strncpy_s (nid.szTip, sizeof (nid.szTip), "TXLib Information", sizeof (nid.szTip));
$ strncpy_s (nid.szInfoTitle, sizeof (nid.szInfoTitle), (title? title : "TXLib сообщает"), sizeof (nid.szInfoTitle) - 1);
$ _tx_vsnprintf_s (nid.szInfo, sizeof (nid.szInfo), format, arg);
$ nid.dwInfoFlags = flags;
$ txOutputDebugPrintf ("\r" _TX_VERSION " - %s: %s (Icon notification)\n", nid.szInfoTitle, nid.szInfo);
$ ok &= !!Shell_NotifyIcon (NIM_ADD, (::NOTIFYICONDATA*) &nid);
$ ok &= !!Shell_NotifyIcon (NIM_MODIFY, (::NOTIFYICONDATA*) &nid);
$ if (nid.hIcon) DestroyIcon (nid.hIcon) asserted;
#else
$ char nid_szInfo[_TX_BUFSIZE] = "";
$ _tx_vsnprintf_s (nid_szInfo, sizeof (nid_szInfo), format, arg);
$ txOutputDebugPrintf ("\r" _TX_VERSION " - %s: %s (Icon notification - NOT displayed)\n", title, nid_szInfo);
$ ok = false;
$ (void)flags; (void)title;
#endif
$ va_end (arg);
return ok;
}
//-----------------------------------------------------------------------------------------------------------------
void _txTrace (const char* file, int line, const char* func, const char* msg /*= NULL*/, ...)
{
unsigned id = GetCurrentThreadId();
const char marks[2][2][3] = {{"uU", "cC"}, {"mM", "??"}};
char mark = marks [id == _txMainThreadId] [id == _txCanvas_ThreadId] [(_txLoc::Cur.inTX > 0)];
char msgStr[_TX_BUFSIZE] = "";
if (msg)
{
va_list arg; va_start (arg, msg);
_tx_vsnprintf_s (msgStr, sizeof (msgStr) - 1, msg, arg);
va_end (arg);
}
txOutputDebugPrintf ("%s - 0x%p %c%c%c%c%c%d [%c] - %-*s (%5d) " "|%*s%s" "%s%s\n",
_TX_VERSION, (void*) &_txInitialized,
"cC"[!!_txConsole], "mM"[_txMain], "dD"[_txIsDll], "rR"[_txRunning], "eE"[_txExit],
_txLoc::Cur.trace, mark,
(int) sizeof (__FILE__) - 1, (file? file : "(NULL file)"), line,
2 * (_txLoc::Cur.inTX - 1) * !!func, "", (func? func : ""),
((*msgStr && func)? ": " : ""), msgStr);
}
//-----------------------------------------------------------------------------------------------------------------
int txOutputDebugPrintf (const char* format, ...)
{
if (!format) return 0;
enum { msgbox = 1, print = 2, compr = 4 };
int options = 0;
for (; format && *format; format++)
{
if (*format == '\a') options |= msgbox;
else if (*format == '\f') options |= print;
else if (*format == '\r') options |= compr;
else break;
}
char text[_TX_BIGBUFSIZE] = "";
va_list arg; va_start (arg, format);
int n = (int) _tx_vsnprintf_s (text, sizeof (text) - 1-1, format, arg); //-V202
va_end (arg);
struct __ { static int trimSpaces (char str[])
{
char *dst = str, *src = str;
for (char d = ' '; d; src++)
if (isspace ((unsigned char)(*src))) { if (d != ' ') *dst++ = d = ' '; }
else *dst++ = d = *src;
return (int) (dst - str - 1); //-V202
}};
if (options & compr) n = __::trimSpaces (text);
OutputDebugString (text);
if (options & print) fprintf (stderr, "%s", text);
if (options & msgbox) txMessageBox (text, "Оказывается, что", MB_ICONEXCLAMATION);
return n;
}
//-----------------------------------------------------------------------------------------------------------------
intptr_t _tx_snprintf_s (char* stream, intptr_t size, const char* format, ...)
{
if (!format) return 0;
va_list arg; va_start (arg, format);
intptr_t ret = _tx_vsnprintf_s (stream, size, format, arg);
va_end (arg);
return ret;
}
//-----------------------------------------------------------------------------------------------------------------
intptr_t _tx_vsnprintf_s (char stream[], intptr_t size, const char format[], va_list arg)
{
if (!stream || !format) return 0;
#if defined (_TRUNCATE)
intptr_t ret = _vsnprintf_s (stream, size, _TRUNCATE, format, arg);
#else
intptr_t ret = _vsnprintf (stream, size, format, arg);
#endif
if (ret < 0 && size >= 4) //-V112
{
const char ellipsis[] = "...";
size_t szEllipsis = sizeof (ellipsis) - 1;
strncpy_s (stream + size - szEllipsis, szEllipsis+1, ellipsis, szEllipsis);
}
return (ret >= 0)? ret : size;
}
//-----------------------------------------------------------------------------------------------------------------
#if defined (__CYGWIN__)
int _getch()
{
termios oldattr = {}; tcgetattr (STDIN_FILENO, &oldattr);
termios newattr = oldattr;
newattr.c_lflag &= ~(ICANON | ECHO);
tcsetattr (STDIN_FILENO, TCSANOW, &newattr);
int ch = getchar();
tcsetattr (STDIN_FILENO, TCSANOW, &oldattr);
return ch;
}
//-----------------------------------------------------------------------------------------------------------------
int _putch (int ch)
{
termios old = {}; tcgetattr (STDOUT_FILENO, &old);
termios cur = old;
cur.c_lflag &= ~ICANON;
cur.c_lflag |= ECHO;
tcsetattr (STDOUT_FILENO, TCSANOW, &cur);
putchar (ch);
tcsetattr (STDOUT_FILENO, TCSANOW, &old);
return ch;
}
//-----------------------------------------------------------------------------------------------------------------
int _kbhit()
{
termios old = {}; tcgetattr (STDIN_FILENO, &old);
termios cur = old;
cur.c_lflag &= ~(ICANON | ECHO);
cur.c_cc[VMIN] = 1;
cur.c_cc[VTIME] = 0;
tcsetattr (STDIN_FILENO, TCSAFLUSH, &cur);
fd_set fd = {}; FD_SET (STDIN_FILENO, &fd);
timeval tv = {};
int res = select (STDIN_FILENO + 1, &fd, NULL, NULL, &tv) && FD_ISSET (STDIN_FILENO, &fd);
tcsetattr (STDIN_FILENO, TCSAFLUSH, &old);
return res;
}
#endif
#endif // TX_COMPILED
//}
//-----------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
//{ Information
//-----------------------------------------------------------------------------------------------------------------
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
const char* txGetModuleFileName (bool fileNameOnly /*= true*/)
{
static char name[MAX_PATH] = "";
if (!*name)
{
if (!GetModuleFileName (NULL, name, sizeof (name) - 1)) *name = 0;
char* ext = strrchr (name, '.');
if (ext) _strlwr_s (ext, sizeof (name) - 1 - (ext - name));
}
assert (*name);
if (fileNameOnly) return name;
static char fullName[MAX_PATH] = "";
strncpy_s (fullName, sizeof (fullName), name, sizeof (fullName) - 1);
char* title = strrchr (fullName, '\\'); if (!title) title = fullName;
char* ext = strrchr (fullName, '.'); if (!ext) ext = fullName + strlen (fullName);
size_t sz = sizeof (fullName) - (ext - fullName);
strncpy_s (ext, sz-1, " - TXLib", sz);
return title + 1;
}
#endif // TX_COMPILED
//-----------------------------------------------------------------------------------------------------------------
inline const char* _txAppInfo()
{
$1 time_t timeT = time (NULL) - clock()/CLOCKS_PER_SEC; //-V104
char timeS[32] = "";
ctime_s (timeS, sizeof (timeS), &timeT);
static char text[_TX_BUFSIZE] = "";
char cwd [MAX_PATH] = "";
_tx_snprintf_s (text, sizeof (text) - 1,
"Developed with:\n\n"
"The Dumb Artist Library (TX Library)\n"
_TX_VERSION "\n" _TX_AUTHOR "\n"
"See license on: http://txlib.ru\n\n"
"TXLib file:" "\t" __FILE__ "\n"
"Compiled:" "\t" __DATE__ " " __TIME__ ", " __TX_COMPILER__ ", %s, %d-bit, " _TX_BUILDMODE "\n"
"Started:" "\t" "%.6s %.4s %.8s\n\n"
"Run file:" "\t" "%s\n"
"Directory:" "\t" "%s",
#if defined (_MSC_VER)
"MSVC Runtime",
#elif defined (__CYGWIN__)
"Cygwin Runtime",
#elif defined (_GCC_VER) && defined (_WIN64)
__mingw_get_crt_info(),
#else
"MinGW Runtime " TX_QUOTE (__MINGW32_MAJOR_VERSION) "." TX_QUOTE (__MINGW32_MINOR_VERSION),
#endif
(sizeof (void*) == sizeof (DWORD))? 32 : 64, //-V112
timeS + 4, timeS + 20, timeS + 11, //-V112 These offsets are ANSI standardized
txGetModuleFileName(),
_getcwd (cwd, sizeof (cwd) - 1));
return text;
}
//}
//-----------------------------------------------------------------------------------------------------------------
//! @}
//}
//=================================================================================================================
//=================================================================================================================
//{ TXLib API implementation
// Реализация TXLib API
//=================================================================================================================
inline const char* txVersion()
{
return _TX_VERSION;
}
//-----------------------------------------------------------------------------------------------------------------
inline unsigned txVersionNumber()
{
return _TX_VER; //-V2517
}
//-----------------------------------------------------------------------------------------------------------------
inline HWND txWindow()
{
$9 return _txCanvas_Window;
}
//-----------------------------------------------------------------------------------------------------------------
inline HDC& txDC()
{
return _txCanvas_BackBuf[0];
}
//-----------------------------------------------------------------------------------------------------------------
inline RGBQUAD* txVideoMemory()
{
return _txCanvas_Pixels;
}
//-----------------------------------------------------------------------------------------------------------------
inline int txGetExtentX (HDC dc /*= txDC()*/)
{
return txGetExtent (dc) .x;
}
//-----------------------------------------------------------------------------------------------------------------
inline int txGetExtentY (HDC dc /*= txDC()*/)
{
return txGetExtent (dc) .y;
}
//-----------------------------------------------------------------------------------------------------------------
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
POINT txGetExtent (HDC dc /*= txDC()*/)
{
$0 static POINT err = {-1, -1};
if (!dc) {$ POINT screen = { GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN) }; return screen; };
if (_TX_DEFAULT_HDC_FAILED (dc)) {$ return err; }
$ BITMAP bmap = {};
$ txGDI (Win32::GetObject (Win32::GetCurrentObject (dc, OBJ_BITMAP), sizeof (bmap), &bmap), dc) asserted;
$ POINT size = { bmap.bmWidth, bmap.bmHeight };
$ return size;
}
//-----------------------------------------------------------------------------------------------------------------
bool txDestroyWindow (HWND wnd /*= txWindow()*/)
{
$1 if (!wnd || !txWindow()) return false;
$ if (wnd != txWindow())
{
$ return !!SendNotifyMessage (txWindow(), _TX_WM_DESTROYWND, 0, (LPARAM) wnd);
}
$ if (SendNotifyMessage (txWindow(), (_txMain? WM_CLOSE : WM_DESTROY), 0, 0) == 0) return false;
$ if (_txMain)
{
$ txNotifyIcon (NIIF_WARNING, NULL, "\n" "Очень, очень плохо завершать программу через txDestroyWindow().\n\n"
"Возвращайтесь через main(), там вам будут рады.\n");
$ Sleep (_TX_TIMEOUT);
}
$ _txWaitFor (!_txCanvas_Window, _TX_TIMEOUT);
$ return _txCanvas_Window == NULL;
}
//-----------------------------------------------------------------------------------------------------------------
HPEN txSetColor (COLORREF color, double thickness /*= 1*/, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return NULL;
$ HPEN pen = Win32::CreatePen ((color == TX_TRANSPARENT? PS_NULL : PS_SOLID), ROUND (thickness), color);
$ if (!pen) return (HPEN) NULL;
$ if (!_txBuffer_Select (pen, dc))
{
$ Win32::DeleteObject (pen);
$ return (HPEN) NULL;
}
$ if (txGDI (Win32::SetTextColor (dc, color), dc) == CLR_INVALID)
{$ return (HPEN) NULL; }
$ return pen;
}
//-----------------------------------------------------------------------------------------------------------------
COLORREF txColor (double red, double green, double blue)
{
$1 if (red > 1) red = 1; if (red < 0) red = 0;
$ if (green > 1) green = 1; if (green < 0) green = 0;
$ if (blue > 1) blue = 1; if (blue < 0) blue = 0;
$ COLORREF color = RGB (ROUND (red * 255), ROUND (green * 255), ROUND (blue * 255));
$ return txSetColor (color)? color : CLR_INVALID;
}
//-----------------------------------------------------------------------------------------------------------------
COLORREF txGetColor (HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return CLR_INVALID;
$ HGDIOBJ obj = txGDI ((Win32::GetCurrentObject (dc, OBJ_PEN)), dc);
$ assert (obj); if (!obj) return CLR_INVALID; //-V547
$ union { EXTLOGPEN extLogPen; LOGPEN LogPen; } buf = {}; //-V2514
$ int size = Win32::GetObject (obj, 0, NULL);
$ Win32::GetObject (obj, sizeof (buf), &buf) asserted;
$ return (size == sizeof (LOGPEN))? buf.LogPen.lopnColor : buf.extLogPen.elpColor;
}
//-----------------------------------------------------------------------------------------------------------------
HBRUSH txSetFillColor (COLORREF color, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return NULL;
$ HBRUSH brush = (color == TX_TRANSPARENT)? (HBRUSH) Win32::GetStockObject (HOLLOW_BRUSH) : Win32::CreateSolidBrush (color);
$ return (_txBuffer_Select (brush, dc))? brush : (Win32::DeleteObject (brush), (HBRUSH) NULL);
}
//-----------------------------------------------------------------------------------------------------------------
COLORREF txFillColor (double red, double green, double blue)
{
$1 if (red > 1) red = 1; if (red < 0) red = 0;
$ if (green > 1) green = 1; if (green < 0) green = 0;
$ if (blue > 1) blue = 1; if (blue < 0) blue = 0;
$ COLORREF color = RGB (ROUND (red * 255), ROUND (green * 255), ROUND (blue * 255));
$ return txSetFillColor (color)? color : CLR_INVALID;
}
//-----------------------------------------------------------------------------------------------------------------
COLORREF txGetFillColor (HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return CLR_INVALID;
$ HGDIOBJ obj = txGDI ((Win32::GetCurrentObject (dc, OBJ_BRUSH)), dc);
$ assert (obj); if (!obj) return CLR_INVALID; //-V547
$ LOGBRUSH buf = {};
$ txGDI ((Win32::GetObject (obj, sizeof (buf), &buf)), dc) asserted;
$ return buf.lbColor;
}
//-----------------------------------------------------------------------------------------------------------------
bool txClear (HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ POINT size = txGetExtent (dc);
$ return txGDI (!!(Win32::PatBlt (dc, 0, 0, size.x, size.y, PATCOPY)), dc);
}
//-----------------------------------------------------------------------------------------------------------------
bool txSetPixel (double x, double y, COLORREF color, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ txGDI ((Win32::SetPixel (dc, ROUND (x), ROUND (y), color)), dc);
$ return true;
}
//-----------------------------------------------------------------------------------------------------------------
bool txPixel (double x, double y, double red, double green, double blue, HDC dc /*= txDC()*/)
{
$1 if (red > 1) red = 1; if (red < 0) red = 0;
$ if (green > 1) green = 1; if (green < 0) green = 0;
$ if (blue > 1) blue = 1; if (blue < 0) blue = 0;
$ return txSetPixel (x, y, RGB (ROUND (red * 255), ROUND (green * 255), ROUND (blue * 255)), dc);
}
//-----------------------------------------------------------------------------------------------------------------
COLORREF txGetPixel (double x, double y, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return CLR_INVALID;
$ return txGDI ((Win32::GetPixel (dc, ROUND (x), ROUND (y))), dc);
}
//-----------------------------------------------------------------------------------------------------------------
bool txLine (double x0, double y0, double x1, double y1, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ bool ok = txGDI ((Win32::MoveToEx (dc, ROUND (x0), ROUND (y0), NULL)), dc);
$ ok &= txGDI ((Win32::LineTo (dc, ROUND (x1), ROUND (y1) )), dc);
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
bool txRectangle (double x0, double y0, double x1, double y1, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ return txGDI ((Win32::Rectangle (dc, ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1))), dc);
}
//-----------------------------------------------------------------------------------------------------------------
bool txPolygon (const POINT points[], int numPoints, HDC dc /*= txDC()*/)
{
$1 if (_TX_ARGUMENT_FAILED (points)) return false;
$ if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ return txGDI (!!(Win32::Polygon (dc, points, numPoints)), dc);
}
//-----------------------------------------------------------------------------------------------------------------
bool txEllipse (double x0, double y0, double x1, double y1, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ return txGDI ((Win32::Ellipse (dc, ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1))), dc);
}
//-----------------------------------------------------------------------------------------------------------------
bool txCircle (double x, double y, double r)
{
$1 return txEllipse (x-r, y-r, x+r, y+r);
}
//-----------------------------------------------------------------------------------------------------------------
bool txArc (double x0, double y0, double x1, double y1, double startAngle, double totalAngle, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ POINT center = { ROUND ((x0 + x1) /2), ROUND ((y0 + y1) /2) };
$ double start = startAngle * txPI/180,
end = (startAngle + totalAngle) * txPI/180;
$ return txGDI (!!(Win32::Arc (dc, ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1),
ROUND (center.x + 1E3*cos (start)), ROUND (center.y - 1E3*sin (start)),
ROUND (center.x + 1E3*cos (end)), ROUND (center.y - 1E3*sin (end)))), dc);
}
//-----------------------------------------------------------------------------------------------------------------
bool txPie (double x0, double y0, double x1, double y1, double startAngle, double totalAngle, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ POINT center = { ROUND ((x0 + x1) /2), ROUND ((y0 + y1) /2) };
$ double start = startAngle * txPI/180,
end = (startAngle + totalAngle) * txPI/180;
$ return txGDI (!!(Win32::Pie (dc, ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1),
ROUND (center.x + 1E3*cos (start)), ROUND (center.y - 1E3*sin (start)),
ROUND (center.x + 1E3*cos (end)), ROUND (center.y - 1E3*sin (end)))), dc);
}
//-----------------------------------------------------------------------------------------------------------------
bool txChord (double x0, double y0, double x1, double y1, double startAngle, double totalAngle, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ POINT center = { ROUND ((x0 + x1) /2), ROUND ((y0 + y1) /2) };
$ double start = startAngle * txPI/180,
end = (startAngle + totalAngle) * txPI/180;
$ return txGDI (!!(Win32::Chord (dc, ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1),
ROUND (center.x + 1E3*cos (start)), ROUND (center.y - 1E3*sin (start)),
ROUND (center.x + 1E3*cos (end)), ROUND (center.y - 1E3*sin (end)))), dc);
}
//-----------------------------------------------------------------------------------------------------------------
bool txFloodFill (double x, double y,
COLORREF color /*= TX_TRANSPARENT*/, DWORD mode /*= FLOODFILLSURFACE*/, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ if (color == TX_TRANSPARENT) color = txGetPixel (x, y, dc);
$ return txGDI (!!(Win32::ExtFloodFill (dc, ROUND (x), ROUND (y), color, mode)), dc);
}
//-----------------------------------------------------------------------------------------------------------------
bool txTextOut (double x, double y, const char text[], HDC dc /*= txDC()*/)
{
$1 if (_TX_ARGUMENT_FAILED (text)) return false;
$ if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ int len = (int) strlen (text); //-V202
$ bool ok = txGDI (!!(Win32::TextOut (dc, ROUND (x), ROUND (y), text, len)), dc);
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
bool txDrawText (double x0, double y0, double x1, double y1, const char text[],
unsigned format /*= DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_WORD_ELLIPSIS*/,
HDC dc /*= txDC()*/)
{
$1 if (_TX_ARGUMENT_FAILED (text)) return false;
$ if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
#if !defined (NDEBUG)
$ if (x0 > x1)
{
$ SetLastError (ERROR_INVALID_DATA);
$ TX_ERROR ("Параметр x0 = %g больше, чем x1 = %g. Текст выводиться не будет.", x0, x1);
}
$ if (y0 > y1)
{
$ SetLastError (ERROR_INVALID_DATA);
$ TX_ERROR ("Параметр y0 = %g больше, чем y1 = %g. Текст выводиться не будет.", y0, y1);
}
#endif
$ RECT r = { ROUND (x0), ROUND (y0), ROUND (x1), ROUND (y1) };
$ if (!strchr (text, '\n')) format |= DT_SINGLELINE;
$ unsigned prev = txSetTextAlign (TA_LEFT | TA_TOP | TA_NOUPDATECP, dc);
$ bool ok = false;
$ if (Win32::DrawText)
{
$ ok = !!txGDI ((Win32::DrawText (dc, text, -1, &r, format)), dc);
$ Win32::GetPixel (dc, 0, 0);
$ ok = true; //-V519
}
else
{
$ txTextOut ((x0 + x1) / 2, (y0 + y1) / 2, text);
$ ok = false;
}
$ txSetTextAlign (prev, dc);
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
HFONT txSelectFont (const char name[], double sizeY, double sizeX /*= -1*/,
int bold /*= FW_DONTCARE*/, bool italic /*= false*/, bool underline /*= false*/,
bool strikeout /*= false*/, double angle /*= 0*/,
HDC dc /*= txDC()*/)
{
$1 if (_TX_ARGUMENT_FAILED (name)) return NULL;
$ if (_TX_DEFAULT_HDC_FAILED (dc)) return NULL;
$ HFONT font = txFontExist (name)?
Win32::CreateFont (ROUND (sizeY), ROUND ((sizeX >= 0)? sizeX : sizeY/3),
ROUND (angle*10), 0, bold, italic, underline, strikeout,
RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, name)
:
(HFONT) Win32::GetStockObject (SYSTEM_FIXED_FONT);
$ _txBuffer_Select (font, dc);
$ return font;
}
//-----------------------------------------------------------------------------------------------------------------
SIZE txGetTextExtent (const char text[], HDC dc /*= txDC()*/)
{
$1 SIZE size = {-1, -1};
$ if (_TX_ARGUMENT_FAILED (text)) return size;
$ if (_TX_DEFAULT_HDC_FAILED (dc)) return size;
$ size_t len = strlen (text);
$ txGDI ((Win32::GetTextExtentPoint32 (dc, text, (int) len, &size)), dc) asserted; //-V202
$ return size;
}
//-----------------------------------------------------------------------------------------------------------------
int txGetTextExtentX (const char text[], HDC dc /*= txDC()*/)
{
$1 return txGetTextExtent (text, dc) .cx;
}
//-----------------------------------------------------------------------------------------------------------------
int txGetTextExtentY (const char text[], HDC dc /*= txDC()*/)
{
$1 return txGetTextExtent (text, dc) .cy;
}
//-----------------------------------------------------------------------------------------------------------------
unsigned txSetTextAlign (unsigned align /*= TA_CENTER | TA_BASELINE*/, HDC dc /*= txDC()*/)
{
$1 if (_TX_DEFAULT_HDC_FAILED (dc)) return false; //-V601
$ return txGDI ((Win32::SetTextAlign (dc, align)), dc);
}
//-----------------------------------------------------------------------------------------------------------------
LOGFONT* txFontExist (const char name[])
{
$1 if (_TX_ARGUMENT_FAILED (name)) return NULL;
$ static LOGFONT font = {};
$ font.lfCharSet = DEFAULT_CHARSET;
$ strncpy_s (font.lfFaceName, sizeof (font.lfFaceName), name, sizeof (font.lfFaceName) - 1);
$ struct tools
{
static int CALLBACK enumFonts (const LOGFONT* fnt, const TEXTMETRIC*, DWORD, LPARAM data)
{
$ if (_TX_ARGUMENT_FAILED (fnt)) return 0;
$ if (_TX_ARGUMENT_FAILED (data)) return 0;
#ifndef __STRICT_ANSI__
$ return _strnicmp (fnt->lfFaceName, ((LOGFONT*)data)->lfFaceName, LF_FACESIZE);
#else
$ return strncmp (fnt->lfFaceName, ((LOGFONT*)data)->lfFaceName, LF_FACESIZE);
#endif
}
};
$ return txGDI ((Win32::EnumFontFamiliesEx (NULL, &font, tools::enumFonts, (LPARAM) &font, 0)), NULL) == 0? &font : NULL;
}
//-----------------------------------------------------------------------------------------------------------------
bool txSelectObject (HGDIOBJ obj, HDC dc /*= txDC()*/)
{
$1 if (_TX_ARGUMENT_FAILED (obj)) return false;
$ if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ return _txBuffer_Select (obj, dc);
}
//-----------------------------------------------------------------------------------------------------------------
HDC txCreateCompatibleDC (double sizeX, double sizeY, HBITMAP bitmap /*= NULL*/, RGBQUAD** pixels /*= NULL*/)
{
$1 POINT size = { ROUND (sizeX), ROUND (sizeY) };
$ HDC dc = _txBuffer_Create (NULL, &size, bitmap, pixels);
$ assert (dc); if (!dc) return NULL; //-V547
$ txSetDefaults (dc);
$ if (!_txCanvas_UserDCs) return dc;
$ txAutoLock _lock;
$ _txCanvas_UserDCs->push_back (dc);
$ if (_txCanvas_UserDCs->size() >= _TX_BUFSIZE)
{$ txNotifyIcon (NIIF_WARNING, NULL, "Вы загрузили уже %d HDC, системе может стать плохо.", (int) _txCanvas_UserDCs->size()); } //-V202
$ return dc;
}
//-----------------------------------------------------------------------------------------------------------------
HDC txCreateDIBSection (double sizeX, double sizeY, RGBQUAD** pixels /*= NULL*/)
{
$1 return txCreateCompatibleDC (sizeX, sizeY, NULL, pixels);
}
//-----------------------------------------------------------------------------------------------------------------
HDC txCreateDIBSection (double sizeX, double sizeY, COLORREF** pixels)
{
$1 return txCreateDIBSection (sizeX, sizeY, (RGBQUAD**) pixels);
}
//-----------------------------------------------------------------------------------------------------------------
HDC txLoadImage (const char filename[], int sizeX /*= 0*/, int sizeY /*= 0*/,
unsigned imageFlags /*= IMAGE_BITMAP*/, unsigned loadFlags /*= LR_LOADFROMFILE*/)
{
$1 if (_TX_ARGUMENT_FAILED (filename && *filename)) return NULL;
$ HBITMAP image = (HBITMAP) Win32::LoadImage ((loadFlags & LR_LOADFROMFILE)? NULL : GetModuleHandle (NULL),
filename, imageFlags, sizeX, sizeY, loadFlags);
$ if (!image) return NULL;
$ HDC dc = txCreateCompatibleDC (sizeX, sizeY, image);
$ if (!(loadFlags & LR_LOADFROMFILE)) return dc;
$ static std::map <std::string, unsigned> loadTimes;
$ std::string file = filename;
$ unsigned time = GetTickCount();
$ if ((long) (time - loadTimes [file]) < _TX_TIMEOUT)
{$ txNotifyIcon (NIIF_WARNING, NULL, "Вы загружаете \"%s\" слишком часто, программа будет тормозить.", filename); }
$ loadTimes [file] = time;
$ return dc;
}
//-----------------------------------------------------------------------------------------------------------------
bool txDeleteDC (HDC* pdc)
{
$1 if (_TX_ARGUMENT_FAILED (pdc)) return false;
$ HDC dc = *pdc;
$ bool ok = _txBuffer_Delete (pdc);
$ if (!ok) return false;
$ if (!_txCanvas_UserDCs) return ok;
$ txAutoLock _lock;
$ for (std::vector <HDC> ::iterator it = _txCanvas_UserDCs->begin(); it != _txCanvas_UserDCs->end(); ++it)
if (*it == dc)
{
$ std::swap (*it, _txCanvas_UserDCs->back());
$ _txCanvas_UserDCs->pop_back();
$ break;
}
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
bool txDeleteDC (HDC dc)
{
$1 return txDeleteDC (&dc);
}
//-----------------------------------------------------------------------------------------------------------------
bool txBitBlt (HDC destImage, double xDest, double yDest, double width, double height,
HDC sourceImage, double xSource /*= 0*/, double ySource /*= 0*/, unsigned operation /*= SRCCOPY*/)
{
$1 if (_TX_HDC_FAILED (destImage)) return false;
$ if (_TX_HDC_FAILED (sourceImage)) return false;
$ POINT size = txGetExtent (sourceImage);
$ if (!width) width = size.x; //-V550
$ if (!height) height = size.y; //-V550
$ return txGDI (!!(Win32::BitBlt (destImage, ROUND (xDest), ROUND (yDest), ROUND (width), ROUND (height),
sourceImage, ROUND (xSource), ROUND (ySource), operation)), destImage);
}
//-----------------------------------------------------------------------------------------------------------------
bool txBitBlt (double xDest, double yDest, HDC sourceImage, double xSource /*= 0*/, double ySource /*= 0*/)
{
$1 if (_TX_TXWINDOW_FAILED()) return false;
$ return txBitBlt (txDC(), xDest, yDest, 0, 0, sourceImage, xSource, ySource);
}
//-----------------------------------------------------------------------------------------------------------------
bool txTransparentBlt (HDC destImage, double xDest, double yDest, double width, double height,
HDC sourceImage, double xSource /*= 0*/, double ySource /*= 0*/, COLORREF transColor /*= TX_BLACK*/)
{
// Это проверки того, правильные ли HDC вы передали в функцию.
// Не бойтесь долларов - <s>это не запрещенная валюта</s> это макросы для отладки TXLib'а.
// При первом чтении это можно пропустить.
$1 if (_TX_HDC_FAILED (destImage)) return false;
$ if (_TX_HDC_FAILED (sourceImage)) return false;
// Это автоматическое определение размеров картинки (точнее, HDC источника - source) с помощью txGetExtent().
// При первом чтении это можно пропустить.
$ POINT size = txGetExtent (sourceImage);
$ if (!width) width = size.x; //-V550
$ if (!height) height = size.y; //-V550
// Это проверка того, что картинка (или ее часть) правильно попадает в окно (точнее, HDC приемника - destination, dest).
// Если она "вылезает" из окна в любую сторону, то Win32::TransparentBlt() не будет работать. Эта проверка происходит только
// в режиме отладки (когда не задан макрос NDEBUG - No Debugging, без отладки).
// При первом чтении это можно пропустить.
#if !defined (NDEBUG)
$ if (!(0 <= xSource && xSource + width <= size.x &&
0 <= ySource && ySource + height <= size.y))
{
$ SetLastError (ERROR_INVALID_DATA);
$ TX_ERROR ("Прямоугольник копируемой области {%g, %g, %g, %g} не полностью лежит внутри изображения-источника {%d, %d, %d, %d}, "
"функция txTransparentBlt() работать не будет.", xSource, ySource, xSource + width, ySource + height, 0, 0, (int) size.x, (int) size.y);
}
#endif
$ bool ok = true;
$ if (Win32::TransparentBlt)
{
// А вот теперь уже надо начать читать.
//
// Ниже - это вызов стандартной Win32::TransparentBlt() из ядра Windows. Погуглите "Windows TransparentBlt function"
// и почитайте про ее параметры.
//
// Как видите, оригинальная функция из Win32 принимает размеры не только исходной, но и итоговой картинки, и если они не
// совпадают, то картинка будет уменьшена или увеличена. TXlib'овская <s>паленая</s> функция TransparentBlt предполагает, что
// эти размеры всегда совпадают, и поэтому при работе с TransparentBlt() масштаб будет всегда 1:1. <s>Так себе решение, но</s>
// это сделано для упрощения вызова функции TransparentBlt().
// Только то, что эти параметры передаются одинаковыми, не дает возможность менять масштаб картинки! // <<--
// // <<--
// ||||| |||||| // <<--
// vvvvv vvvvvv // <<--
// <<--
$ ok &= txGDI (!!(Win32::TransparentBlt (destImage, ROUND (xDest), ROUND (yDest), ROUND (width), ROUND (height), // <<<<
sourceImage, ROUND (xSource), ROUND (ySource), ROUND (width), ROUND (height), transColor)), // <<<<
destImage); // <<--
// ^^^^^ ^^^^^^ // <<--
// ||||| |||||| // <<--
// // <<--
} // См. "TransparentBlt function" в Google, ищите смысл параметров wSrc и wDest (hSrc и hDest). Думайте! // <<--
else
{
$ ok &= txGDI (!!(Win32::BitBlt (destImage, ROUND (xDest), ROUND (yDest), ROUND (width), ROUND (height),
sourceImage, ROUND (xSource), ROUND (ySource), SRCCOPY)),
destImage);
}
// В TXLib-овской функции txTransparentBlt() проверок и комментариев больше, чем рабочего кода, и это как бы намекает, что
// нетрудно сделать свою аналогичную функцию без ограничений масштаба отображения. <s>Если ты дочитал до этого места,</s>
// пересядь с иглы TXLib'а на поверхность GDI Win32, <s>хотя GDI тоже так себе, так что лучше заюзай GDI+, SFML, OpenGL
// или DirectX, будет круто. Хотя это и сложнее.</s>
// Пожалуйста, не надо бездумно копировать себе в программу код из TXLib'а. Осмыслите его и напишите свою функцию сами,
// иначе вы породите невнятный паленый код и безнадежно испортите себе карму. :((
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
bool txTransparentBlt (double xDest, double yDest, HDC sourceImage,
COLORREF transColor /*= TX_BLACK*/, double xSource /*= 0*/, double ySource /*= 0*/)
{
$1 if (_TX_TXWINDOW_FAILED()) return false;
$ return txTransparentBlt (txDC(), xDest, yDest, 0, 0, sourceImage, xSource, ySource, transColor);
}
//-----------------------------------------------------------------------------------------------------------------
bool txAlphaBlend (HDC destImage, double xDest, double yDest, double width, double height,
HDC sourceImage, double xSource /*= 0*/, double ySource /*= 0*/, double alpha /*= 1.0*/)
{
$1 if (_TX_HDC_FAILED (destImage)) return false;
$ if (_TX_HDC_FAILED (sourceImage)) return false;
$ POINT size = txGetExtent (sourceImage);
$ if (!width) width = size.x; //-V550
$ if (!height) height = size.y; //-V550
#if !defined (NDEBUG)
$ if (!(0 <= xSource && xSource + width <= size.x &&
0 <= ySource && ySource + height <= size.y))
{
$ SetLastError (ERROR_INVALID_DATA);
$ TX_ERROR ("Прямоугольник копируемой области {%g, %g, %g, %g} не полностью лежит внутри изображения-источника {%d, %d, %d, %d}, "
"функция txAlphaBlend() работать не будет.", xSource, ySource, xSource + width, ySource + height, 0, 0, (int) size.x, (int) size.y);
}
#endif
$ if (alpha < 0) alpha = 0;
$ if (alpha > 1) alpha = 1;
$ BITMAP bmap = { 0, 0, 0, 0, 0, 24 };
$ bool ok = !!Win32::GetObject (txGDI ((Win32::GetCurrentObject (sourceImage, OBJ_BITMAP)), sourceImage), sizeof (bmap), &bmap);
$ BLENDFUNCTION blend = { AC_SRC_OVER, 0, (BYTE) ROUND (alpha * 255), (BYTE) ((bmap.bmBitsPixel == 32)? AC_SRC_ALPHA : 0) }; //-V112 //-V821 //-V2551
$ if (Win32::AlphaBlend)
{
$ ok &= txGDI (!!(Win32::AlphaBlend (destImage, ROUND (xDest), ROUND (yDest), ROUND (width), ROUND (height),
sourceImage, ROUND (xSource), ROUND (ySource), ROUND (width), ROUND (height), blend)),
destImage);
}
else
{
$ ok &= txGDI (!!(Win32::BitBlt (destImage, ROUND (xDest), ROUND (yDest), ROUND (width), ROUND (height),
sourceImage, ROUND (xSource), ROUND (ySource), SRCCOPY)),
destImage);
$ ok = false; //-V519
}
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
bool txAlphaBlend (double xDest, double yDest, HDC sourceImage,
double xSource /*= 0*/, double ySource /*= 0*/, double alpha /*= 1.0*/)
{
$1 if (_TX_TXWINDOW_FAILED()) return false;
$ return txAlphaBlend (txDC(), xDest, yDest, 0, 0, sourceImage, xSource, ySource, alpha);
}
//-----------------------------------------------------------------------------------------------------------------
HDC txUseAlpha (HDC image)
{
$1 if (_TX_HDC_FAILED (image)) return NULL;
$ HBITMAP bitmap = (HBITMAP) Win32::GetCurrentObject (image, OBJ_BITMAP);
$ if (!bitmap) return NULL;
$ DIBSECTION dib = {};
$ Win32::GetObject (bitmap, sizeof (dib), &dib) asserted;
$ POINT size = { dib.dsBm.bmWidth, dib.dsBm.bmHeight };
$ BITMAPINFO info = {{ sizeof (info), size.x, size.y, 1, (WORD) (sizeof (RGBQUAD) * 8), BI_RGB }};
$ RGBQUAD* buf = NULL;
$ bool isDIB = (dib.dsBm.bmPlanes == 1 &&
dib.dsBm.bmBitsPixel == sizeof (RGBQUAD) * 8 &&
dib.dsBmih.biCompression == DIB_RGB_COLORS &&
dib.dsBm.bmBits);
$ if (!isDIB)
{
$ buf = new (std::nothrow) RGBQUAD [size.x * size.y]; //-V121
$ if (!buf) return NULL;
$ Win32::GetDIBits (image, bitmap, 0, size.y, buf, &info, DIB_RGB_COLORS) asserted;
}
else
{
$ buf = (RGBQUAD*) dib.dsBm.bmBits;
}
$ for (int y = 0; y < size.y; y++)
for (int x = 0; x < size.x; x++)
{
RGBQUAD* color = &buf [x + y * size.x]; // Get color at (x, y) within image buffer //-V108
color->rgbRed = (BYTE) ROUND (color->rgbRed * color->rgbReserved / 255.0);
color->rgbGreen = (BYTE) ROUND (color->rgbGreen * color->rgbReserved / 255.0);
color->rgbBlue = (BYTE) ROUND (color->rgbBlue * color->rgbReserved / 255.0);
}
$ if (!isDIB)
{
$ Win32::SetDIBitsToDevice (image, 0, 0, size.x, size.y, 0, 0, 0, size.y, buf, &info, DIB_RGB_COLORS) asserted;
$ delete[] buf;
}
$ return image;
}
//-----------------------------------------------------------------------------------------------------------------
bool txSaveImage (const char filename[], HDC dc /*= txDC()*/)
{
$1 if (_TX_ARGUMENT_FAILED (filename)) return false;
$ if (_TX_DEFAULT_HDC_FAILED (dc)) return false;
$ POINT size = txGetExtent (dc);
$ size_t szHdrs = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER), //-V119
szImg = (size.x * size.y) * sizeof (RGBQUAD); //-V104
$ BITMAP bmap = {};
$ BITMAPFILEHEADER hdr = { 0x4D42 /* 'MB' */, (DWORD) (szHdrs + szImg), 0, 0, (DWORD) szHdrs }; //-V202
$ BITMAPINFOHEADER info = { sizeof (info), size.x, size.y, 1, (WORD) (sizeof (RGBQUAD) * 8), BI_RGB };
$ RGBQUAD* buf = NULL;
$ bool ok = true;
$ ok &= !!Win32::GetObject (Win32::GetCurrentObject (dc, OBJ_BITMAP), sizeof (bmap), &bmap);
if (!ok) {$ return false; }
$ if (!bmap.bmBits)
{
$ buf = new (std::nothrow) RGBQUAD [size.x * size.y]; //-V121
$ ok &= (buf != NULL);
$ int res = Win32::GetDIBits (dc, (HBITMAP) Win32::GetCurrentObject (dc, OBJ_BITMAP), 0, size.y,
buf, (BITMAPINFO*) &info, DIB_RGB_COLORS);
if (res == ERROR_INVALID_PARAMETER) {$ SetLastError (res); }
$ ok &= !!res;
}
else
{
$ buf = (RGBQUAD*) bmap.bmBits;
}
$ FILE* f = NULL;
$ if (ok) fopen_s (&f, filename, "wb");
$ ok &= (f != NULL);
$ if (ok) ok &= (fwrite (&hdr, sizeof (hdr), 1, f) == 1); //-V575 //-V595
$ if (ok) ok &= (fwrite (&info, sizeof (info), 1, f) == 1);
$ if (ok) ok &= (fwrite (buf, szImg, 1, f) == 1); //-V575
$ ok &= (f && fclose (f) == 0);
$ if (!bmap.bmBits)
{
$ delete[] buf;
$ buf = NULL;
}
$ return ok;
}
//-----------------------------------------------------------------------------------------------------------------
double txSleep (double time)
{
$1 LARGE_INTEGER start = {};
$ QueryPerformanceCounter (&start) asserted;
$ LARGE_INTEGER freq = {};
$ QueryPerformanceFrequency (&freq) asserted;
$ int lock = _txCanvas_RefreshLock;
$ _txCanvas_RefreshLock = 0;
$ HWND wnd = txWindow();
if (wnd) {$ RedrawWindow (wnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_UPDATENOW); }
$ Sleep (ROUND ((time >= 0)? time : 0));
$ _txCanvas_RefreshLock = lock;
$ LARGE_INTEGER stop = {};
$ QueryPerformanceCounter (&stop) asserted;
$ return 1000.0 * (double) (stop.QuadPart - start.QuadPart) / (double) freq.QuadPart;
}
//-----------------------------------------------------------------------------------------------------------------
bool txLock (bool wait /*= true*/)
{
$0 if (_txCanvas_RefreshLock <= 0 || _txExit) Sleep (0);
$ if (wait) {$ return EnterCriticalSection (&_txCanvas_LockBackBuf), true; } //-V1048
else {$ return !!TryEnterCriticalSection (&_txCanvas_LockBackBuf); }
}
//-----------------------------------------------------------------------------------------------------------------
bool txUnlock()
{
$0 LeaveCriticalSection (&_txCanvas_LockBackBuf);
$ if (_txCanvas_RefreshLock <= 0 || _txExit) Sleep (0);
$ return false;
}
#endif // TX_COMPILED
//-----------------------------------------------------------------------------------------------------------------
template <typename T>
inline T txUnlock (T value)
{
$1 txUnlock();
$ return value;
}
//-----------------------------------------------------------------------------------------------------------------
inline void txRedrawWindow()
{
$1 txSleep (0);
}
//-----------------------------------------------------------------------------------------------------------------
inline int txUpdateWindow (int update /*= true*/)
{
$1 return _txCanvas_SetRefreshLock (update >= 0? (int) !update : -update);
}
//-----------------------------------------------------------------------------------------------------------------
inline int txBegin()
{
$1 _txCanvas_SetRefreshLock (_txCanvas_RefreshLock + 1);
$ return _txCanvas_RefreshLock;
}
//-----------------------------------------------------------------------------------------------------------------
inline int txEnd()
{
$1 _txCanvas_SetRefreshLock (_txCanvas_RefreshLock - 1);
$ return _txCanvas_RefreshLock;
}
//-----------------------------------------------------------------------------------------------------------------
inline POINT txMousePos()
{
$1 POINT pos = {};
$ GetCursorPos (&pos);
$ if (txWindow())
{$ ScreenToClient (txWindow(), &pos); }
$ return pos;
}
//-----------------------------------------------------------------------------------------------------------------
inline double txMouseX()
{
return (double) txMousePos() .x;
}
//-----------------------------------------------------------------------------------------------------------------
inline double txMouseY()
{
return (double) txMousePos() .y;
}
//-----------------------------------------------------------------------------------------------------------------
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
unsigned txMouseButtons()
{
$1 HWND txWnd = txWindow();
$ HWND foreground = GetForegroundWindow();
$ if ((txWnd && (foreground == txWnd)) ||
(!txWnd && (foreground == Win32::GetConsoleWindow())))
{
$ return ((GetAsyncKeyState (VK_LBUTTON) & 0x8000) >> 15) | // MSB to bit 0
((GetAsyncKeyState (VK_RBUTTON) & 0x8000) >> 14) | // MSB to bit 1
((GetAsyncKeyState (VK_MBUTTON) & 0x8000) >> 13); // MSB to bit 2
}
else
{$ return 0; }
}
//-----------------------------------------------------------------------------------------------------------------
unsigned txSetConsoleAttr (unsigned color /*= FOREGROUND_LIGHTGRAY*/)
{
unsigned oldAttr = txGetConsoleAttr();
SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), (WORD) color);
SetConsoleTextAttribute (GetStdHandle (STD_ERROR_HANDLE), (WORD) color);
return oldAttr;
}
//-----------------------------------------------------------------------------------------------------------------
unsigned txGetConsoleAttr()
{
CONSOLE_SCREEN_BUFFER_INFO con = {};
con.wAttributes = FOREGROUND_LIGHTGRAY;
GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &con) ||
GetConsoleScreenBufferInfo (GetStdHandle (STD_ERROR_HANDLE), &con);
return con.wAttributes;
}
//-----------------------------------------------------------------------------------------------------------------
POINT txSetConsoleCursorPos (double x, double y)
{
$1 POINT fontSz = txGetConsoleFontSize();
$ CONSOLE_SCREEN_BUFFER_INFO con = {};
$ GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &con) asserted;
$ COORD pos = { (short) ROUND (1.0 * x / fontSz.x + con.srWindow.Left),
(short) ROUND (1.0 * y / fontSz.y + con.srWindow.Top ) };
$ SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), pos) asserted;
$ POINT prev = { ROUND ((con.dwCursorPosition.X - con.srWindow.Left) * fontSz.x),
ROUND ((con.dwCursorPosition.Y - con.srWindow.Top ) * fontSz.y) };
$ return prev;
}
//-----------------------------------------------------------------------------------------------------------------
POINT txGetConsoleCursorPos()
{
$1 POINT fontSz = txGetConsoleFontSize();
$ CONSOLE_SCREEN_BUFFER_INFO con = {};
$ GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &con) asserted;
$ POINT pos = { ROUND ((con.dwCursorPosition.X - con.srWindow.Left) * fontSz.x),
ROUND ((con.dwCursorPosition.Y - con.srWindow.Top ) * fontSz.y) };
$ return pos;
}
//-----------------------------------------------------------------------------------------------------------------
POINT txGetConsoleExtent()
{
$1 CONSOLE_SCREEN_BUFFER_INFO con = {};
$ GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &con) asserted;
$ POINT size = { con.srWindow.Right - con.srWindow.Left + 1,
con.srWindow.Bottom - con.srWindow.Top + 1 };
$ return size;
}
//-----------------------------------------------------------------------------------------------------------------
bool txClearConsole()
{
$1 HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
$ CONSOLE_SCREEN_BUFFER_INFO con = {};
$ GetConsoleScreenBufferInfo (out, &con) asserted;
$ COORD start = {con.srWindow.Left, con.srWindow.Top};
$ DWORD len = (con.srWindow.Right - con.srWindow.Left + 1) *
(con.srWindow.Bottom - con.srWindow.Top + 1);
$ DWORD written = 0;
$ FillConsoleOutputCharacter (out, 0x20 /*' '*/, len, start, &written) asserted; //-V112
$ FillConsoleOutputAttribute (out, con.wAttributes, len, start, &written) asserted;
$ SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), start) asserted;
$ return written == len;
}
//-----------------------------------------------------------------------------------------------------------------
POINT txGetConsoleFontSize()
{
$1 Win32::CONSOLE_FONT_INFO font = {0, {8, 16}};
$ _TX_CALL (Win32::GetCurrentConsoleFont, (GetStdHandle (STD_OUTPUT_HANDLE), false, &font));
$ SIZE size = { font.dwFontSize.X, font.dwFontSize.Y };
if (_txCanvas_BackBuf[1]) {$ txGDI (Win32::GetTextExtentPoint32 (_txCanvas_BackBuf[1], "W", 1, &size), txDC()); } //-V501
if (size.cx == 0) {$ size.cx = 1; }
if (size.cy == 0) {$ size.cy = 1; }
$ POINT sizeFont = { size.cx, size.cy };
$ return sizeFont;
}
//-----------------------------------------------------------------------------------------------------------------
bool txTextCursor (bool blink /*= true*/)
{
$1 bool old = _txConsole_IsBlinking;
$ _txConsole_IsBlinking = blink;
$ return old;
}
//-----------------------------------------------------------------------------------------------------------------
bool txPlaySound (const char filename[] /*= NULL*/, DWORD mode /*= SND_ASYNC*/)
{
$1 mode |= SND_FILENAME | SND_NODEFAULT | SND_NOWAIT;
$ if (mode & SND_LOOP) mode = (mode & ~SND_SYNC) | SND_ASYNC;
$ if (!filename) mode = SND_PURGE;
$ return !!Win32::PlaySound (filename, NULL, mode);
}
//-----------------------------------------------------------------------------------------------------------------
int txSpeak (const char* text, ...)
{
$1 bool verbose = false; (void) verbose;
$ bool async = false; (void) async;
$ for (; text && *text; text++)
{
if (*text == '\a') {$ async = true; }
else if (*text == '\v') {$ verbose = true; }
else break;
}
$ char textA [_TX_BUFSIZE] = "You asked to speak empty text. I would rather say that TX Library is cool! Cats rules!";
$ va_list arg; va_start (arg, text);
if (text && *text) {$ _tx_vsnprintf_s (textA, sizeof (textA) - 1, text, arg); }
$ va_end (arg);
if (text && verbose) {$ printf ("%s", textA); }
#ifdef TX_USE_SPEAK
$ int time = GetTickCount();
$ static wchar_t textW [_TX_BUFSIZE * sizeof (wchar_t)] = L"";
$ MultiByteToWideChar (_TX_CODEPAGE, 0, textA, -1, textW, sizearr (textW));
$ static ISpVoice* voice = NULL;
$ if (text && !voice)
{
$ HRESULT res = Win32::CoInitialize (NULL);
if (res == S_OK) {$ Win32::CoCreateInstance (Win32::CLSID_SpVoice, NULL, CLSCTX_ALL, Win32::IID_ISpVoice, (void**) &voice); }
}
$ if (text && voice)
{
$ Win32::_fpreset();
$ voice->Speak (textW, SPF_PERSIST_XML | SPF_PURGEBEFORESPEAK | ((*textW == '<')? SPF_IS_XML : 0) | (async? SPF_ASYNC : 0), NULL);
$ tx_fpreset();
}
$ if (!text && voice)
{
$ voice->Release();
$ voice = NULL;
$ Win32::CoUninitialize();
}
$ return (voice)? GetTickCount() - time : -1;
#else
$ if (text)
{
$ unsigned oldAttr = txSetConsoleAttr (FOREGROUND_LIGHTRED | BACKGROUND_BLACK);
$ txNotifyIcon (NIIF_ERROR, "txSpeak(): Не могу произнести (нужен TX_USE_SPEAK, см. TXLib Help)", "\n" "%s", textA);
$ txSetConsoleAttr (oldAttr);
}
$ return -1;
#endif
}
//-----------------------------------------------------------------------------------------------------------------
intptr_t txPlayVideo (int x, int y, int width, int height, const char fileName[],
double zoom /*= 0*/, double gain /*= 1*/, HWND wnd /*= txWindow()*/)
{
$1 if (wnd && wnd == txWindow() && _TX_TXWINDOW_FAILED()) return -1;
$ int time = GetTickCount(); //-V2551
$ static char processUID [64] = "";
if (!*processUID)
{
$ FILETIME startTime = {}, null = {};
$ GetProcessTimes (GetCurrentProcess(), &startTime, &null, &null, &null) asserted;
$ _snprintf_s (processUID, sizeof (processUID) - 1, "TXLib[%08X%08X]::txPlayVideo",
(unsigned) startTime.dwHighDateTime, (unsigned) startTime.dwLowDateTime) < (int) sizeof (processUID) asserted;
}
$ if (!fileName)
{
$ _txTaskKill ("vlc.exe", processUID, 0); // Kill'em all, by command line pattern
$ return 0;
}
$ static const char* vlcPath = _txPlayVideo_FindVLC();
$ if (!vlcPath || _access (vlcPath, 0) != 0)
{
$ static int once = false; //-V601
$ if (*fileName && !once++)
{$ txOutputDebugPrintf ("\a" "Не найден видеопроигрыватель VideoLAN (vlc.exe). Cкачайте его с сайта VideoLAN.org "
"и установите. Без установки VideoLAN видео воспроизводиться не будет :(\n\n"
"--\n" "Всегда Ваша, функция " /* как бы */ "txPlayVideo()...\n"
"P.S. См. мое описание в TXLib Help."); }
$ return INT_MIN; //-V109
}
$ bool async = false;
if (*fileName == '\a') {$ async = true; fileName++; }
$ RECT rect = {};
if (wnd) {$ GetClientRect (wnd, &rect); }
if (!width) {$ width = rect.right; }
if (!height) {$ height = rect.bottom; }
// Create a child window to hold the video stream
$ const char* errPos = "ВНЕЗАПНО";
$ volatile HWND child = NULL;
$ if (wnd && (wnd == txWindow()))
{
$ const char* wndClass = txRegisterClass ("txPlayVideo", _txPlayVideo_WndProc, 0, NULL_BRUSH, 1);
$ static int number = 1;
$ CREATESTRUCT createData = { NULL, NULL, (HMENU) (size_t) number++, txWindow(), height, width, y, x,
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, __func__, wndClass };
$ child = txCreateExtraWindow (createData);
$ if (!child)
{
$ txNotifyIcon (NIIF_ERROR, "txPlayVideo() сообщает", "\n" "%s",
strstr (_txError (NULL, 0, NULL, 0, "\f" "Не могу создать окно для видео :("), errPos));
$ return INT_MIN+3; //-V109
}
$ BringWindowToTop (child);
$ wnd = child;
}
// Build the command line
if (!zoom && !wnd) {$ zoom = 1; }
$ char sZoom [64] = "--autoscale";
if (zoom) {$ _snprintf_s (sZoom, sizeof (sZoom) - 1, "--no-autoscale --zoom=%.10g", zoom) < (int) sizeof (sZoom) asserted; } //-V550
$ static char cmd [MAX_PATH*2 + 1024] = "";
$ _snprintf_s (cmd, sizeof (cmd) - 1, "\"%s\" \"%s\" vlc://quit"
" %s --gain=%.10g --drawable-hwnd=%p --video-title=\"%s\" --logfile=%s"
" --live-caching=500 --network-caching=500 --quiet-synchro --no-embedded-video --file-logging"
" --ignore-config --reset-config --no-one-instance --play-and-exit"
" --intf=dummy --dummy-quiet --quiet --no-video-deco --no-video-title-show --no-stats --no-sub-autodetect-file"
" --no-disable-screensaver --no-snapshot-preview --no-auto-preparse --no-mouse-events --no-keyboard-events",
vlcPath, (*fileName? fileName : "fileName"), sZoom, gain, (void*) wnd, processUID, _txLogName) < (int) sizeof (cmd) asserted;
$ txOutputDebugPrintf ("txPlayVideo (%d, %d, %d, %d, \"%s\", %g, %g, %p): [%s]\n\n",
x, y, width, height, fileName, zoom, gain, (void*) wnd, cmd);
$ if (!*fileName)
{
if (child) {$ txDestroyWindow (child); }
$ return (intptr_t) cmd;
}
$ if (!strstr (fileName, "://") && _access (fileName, 0) != 0)
{
$ txNotifyIcon (NIIF_ERROR, "txPlayVideo() сообщает", "\n" "%s",
strstr (_txError (NULL, 0, NULL, 0, "\f" "Не найден файл \"%s\"", fileName), errPos));
if (child) {$ txDestroyWindow (child); }
$ return INT_MIN+1; //-V109
}
// Run VLC, run
$ PROCESS_INFORMATION vlc = {};
$ STARTUPINFO start = { sizeof (start) };
$ DWORD ret = 0;
$ if (CreateProcess (NULL, cmd, NULL, NULL, true, 0, NULL, NULL, &start, &vlc) &&
vlc.hProcess && vlc.hThread)
{
$ if (child)
{
$ assert (wnd == child); //-V547
$ SetWindowLongPtr (wnd, GWLP_USERDATA, (LONG_PTR) vlc.hProcess); //-V107
}
$ if (!async)
{
$ WaitForSingleObject (vlc.hProcess, INFINITE);
$ GetExitCodeProcess (vlc.hProcess, &ret) asserted;
}
$ if (!child)
{
$ CloseHandle (vlc.hProcess) asserted;
}
$ CloseHandle (vlc.hThread) asserted;
$ return (async? (intptr_t) wnd : (ret == 0)? time - GetTickCount() : - (int) ret); //-V105
}
else
{
$ txNotifyIcon (NIIF_ERROR, "txPlayVideo() сообщает", "%s",
strstr (_txError (NULL, 0, NULL, 0, "\f" "Ошибка запуска VideoLAN (%s)", cmd), errPos));
$ if (child)
{$ txDestroyWindow (child); }
$ return INT_MIN+4; //-V112 //-V109
}
#undef PROCESS_UID_
}
//-----------------------------------------------------------------------------------------------------------------
intptr_t txPlayVideo (const char fileName[], double zoom /*= 0*/, double gain /*= 0*/, HWND wnd /*= txWindow()*/)
{
$1 return txPlayVideo (0, 0, 0, 0, fileName, zoom, gain, wnd);
}
//-----------------------------------------------------------------------------------------------------------------
LRESULT CALLBACK _txPlayVideo_WndProc (HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar)
{
const UINT_PTR checkTimer = 1;
switch (msg)
{
case WM_CREATE:
{
$1 SetTimer (wnd, checkTimer, 5*_txWindowUpdateInterval, NULL) asserted;
}
break;
case WM_DESTROY:
{
$1 KillTimer (wnd, checkTimer) asserted;
$ HANDLE vlc = (HANDLE)(uintptr_t) GetWindowLongPtr (wnd, GWLP_USERDATA);
$ if (vlc)
{
$ Win32::TerminateProcess (vlc, 0);
$ CloseHandle (vlc) asserted;
$ SetWindowLongPtr (wnd, GWLP_USERDATA, 0);
}
}
break;
case WM_TIMER:
{
HANDLE vlc = (HANDLE)(uintptr_t) GetWindowLongPtr (wnd, GWLP_USERDATA);
if (vlc && WaitForSingleObject (vlc, 0) != WAIT_TIMEOUT)
{
$1 DestroyWindow (wnd) asserted;
}
}
break;
default: //-V2522
break;
}
return DefWindowProc (wnd, msg, wpar, lpar);
}
//-----------------------------------------------------------------------------------------------------------------
const char* _txPlayVideo_FindVLC()
{
$1 static char vlcPath [MAX_PATH] = "";
$ if (SearchPath (NULL, "vlc.bat", NULL, sizeof (vlcPath), vlcPath, NULL))
{
if (_access (vlcPath, 0) == 0) {$ return vlcPath; }
}
$ if (SearchPath (NULL, "vlc.exe", NULL, sizeof (vlcPath), vlcPath, NULL))
{
if (_access (vlcPath, 0) == 0) {$ return vlcPath; }
}
$ if (txRegQuery ("HKLM\\Software\\VideoLAN\\VLC", NULL, vlcPath, sizeof (vlcPath)))
{
if (_access (vlcPath, 0) == 0) {$ return vlcPath; }
}
$ if (txRegQuery ("HKLM\\Software\\VideoLAN\\VLC", "InstallDir", vlcPath, sizeof (vlcPath)))
{
$ strncat_s (vlcPath, sizeof (vlcPath) - 1, "\\vlc.exe", INT_MAX);
if (_access (vlcPath, 0) == 0) {$ return vlcPath; }
}
$ strncpy_s (vlcPath, sizeof (vlcPath), "C:\\Program Files" "\\VideoLAN\\VLC\\vlc.exe", UINT_MAX); //-V106
{
if (_access (vlcPath, 0) == 0) {$ return vlcPath; }
}
$ strncpy_s (vlcPath, sizeof (vlcPath), "C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe", UINT_MAX); //-V106
{
if (_access (vlcPath, 0) == 0) {$ return vlcPath; }
}
$ return NULL;
}
//-----------------------------------------------------------------------------------------------------------------
HRESULT txSetProgress (double percent, unsigned type /*= TBPF_NORMAL*/, HWND wnd /*= NULL*/)
{
$1 static double oldPercent = 100;
if (percent < 0) {$ percent = MIN (oldPercent, 100); }
else {$ oldPercent = percent; }
$ HRESULT res = S_FALSE;
#if defined (__ITaskbarList3_INTERFACE_DEFINED__)
$ HRESULT init = Win32::CoInitialize (NULL);
$ bool ok = true;
$ res = S_OK;
$ ITaskbarList3* taskbar = NULL;
if (ok) {$ res = Win32::CoCreateInstance (Win32::CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, Win32::IID_ITaskbarList3, (void**) &taskbar); }
$ ok &= !!taskbar && (res == S_OK);
if (!wnd) {$ wnd = txWindow(); }
if (ok && taskbar) {$ res = taskbar->SetProgressValue (wnd, ROUND (percent), 100); ok &= (res == S_OK); }
if (ok && taskbar) {$ res = taskbar->SetProgressState (wnd, (TBPFLAG) type); ok &= (res == S_OK); }
if (wnd == txWindow()) {$ wnd = Win32::GetConsoleWindow(); }
if (ok && taskbar) {$ res = taskbar->SetProgressValue (wnd, ROUND (percent), 100); ok &= (res == S_OK); }
if (ok && taskbar) {$ res = taskbar->SetProgressState (wnd, (TBPFLAG) type); ok &= (res == S_OK); }
if (taskbar) {$ taskbar->Release(); }
if (init == S_OK) {$ Win32::CoUninitialize(); }
#endif
(void) type; (void) wnd;
$ return res;
}
#endif // TX_COMPILED
//-----------------------------------------------------------------------------------------------------------------
// +--<<< Это не те символы, что вы ищете :)
// V Полезно смотреть не только вверх, но и вниз
inline WNDPROC txSetWindowsHook (WNDPROC wndProc /*= NULL*/)
{
$1 WNDPROC old = _txAltWndProc; _txAltWndProc = wndProc;
$ return old;
}
//-----------------------------------------------------------------------------------------------------------------
// +--<<< А это, наконец, искомое определение этой функции.
// | Смотрите по сторонам! Нужная вам функция где-то рядом.
// |
// v
inline bool txIDontWantToHaveAPauseAfterMyProgramBeforeTheWindowWillClose_AndIWillNotBeAskingWhereIsMyPicture()
{
txMessageBox ("Это запланированная ошибка. Такое бывает. Вы хотели вызвать:\n\n"
"txIDontWantToHaveAPauseAfterMyProgramBeforeTheWindowWillClose_AndIWillNotBeAskingWhereIsMyPicture()\n\n"
"Хоть вы долго [копировали]набирали это имя, на самом деле эта функция не реализована. "
"Есть другая функция, которая убирает авто-паузу в конце программы, но в хелпе про нее не написано.\n\n"
"Но не все так плохо. Определение нужной функции есть в исходных текстах TXLib.h, оно лежит рядом "
"с определением той функции с длинным названием, которую вы сейчас вызвали.\n\n"
"Нажмите в редакторе Ctrl+O, найдите и откройте файл TXLib.h (он лежит в папке, куда вы "
"установили TXLib), затем нажмите Ctrl+F и ищите \"txIDontWant\". Удачи!\n\n",
"Не получилось", MB_ICONSTOP);
// The truth is out there... (C++files)
return false;
}
//-----------------------------------------------------------------------------------------------------------------
// Bingo! Now you are learned to use the Source, Luke. And may the Source be with you.
inline bool txDisableAutoPause()
{
_txExit = true;
return true;
}
// P.S. This library contains more undocumented functions. Search them via "Luke" keyword.
//-----------------------------------------------------------------------------------------------------------------
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
void _txDump (const void* address, const char name[] /*= "_txDump()"*/, bool pause /*= true*/)
{
$1 assert (!_txIsBadReadPtr (address));
$ const unsigned char* addr = (const unsigned char*) address;
$ const int stdout_fileno = 1; // Not all g++ packages contain STDOUT_FILENO
$ const int _o_u16text = 0x00020000; // and _O_U16TEXT
$ bool istty = _txIsTTY (1);
$ int mode = _O_TEXT;
$ int oldMode = _setmode (stdout_fileno, mode);
$ unsigned oldCP = GetConsoleOutputCP();
$ unsigned cp = 1251; SetConsoleOutputCP (cp); //-V581
$ unsigned attr = txGetConsoleAttr();
$ txSetConsoleAttr (FOREGROUND_WHITE);
$ printf ("\n%*.*s ", (int) sizeof (address) * 2, (int) sizeof (address) * 2, ((name)? name : ""));
$ txSetConsoleAttr (FOREGROUND_YELLOW);
$ for (unsigned x = 0; x < 16; x++) printf ("%02X ", x);
$ for (unsigned x = 0; x < 16; x++) printf ("%X", x);
$ const wchar_t* xlat[33] = {L"\xB7" /* 00 - NUL - NULL */, L"\x263A" /* 01 - SOH - Start of header */,
L"\x263B" /* 02 - STX - Start of text */, L"\x2665" /* 03 - ETX - End of text */,
L"\x2666" /* 04 - EOT - End of transm. */, L"\x2663" /* 05 - ENQ - Enquiry */,
L"\x2660" /* 06 - ACK - Acknowledgment */, L"\x2022" /* 07 - BEL - Bell */,
L"\x25D8" /* 08 - BS - Backspace */, L"\x25CB" /* 09 - HT - Horizontal tab */,
L"\x25D9" /* 10 - LF - Line feed */, L"\x2642" /* 11 - VT - Vertical tab */,
L"\x2640" /* 12 - FF - Form feed */, L"\x266A" /* 13 - CR - Carriage return */,
L"\x266B" /* 14 - SO - Shift out */, L"\x263C" /* 15 - SI - Shift in */,
L"\x25BA" /* 16 - DLE - Data link escape */, L"\x25C4" /* 17 - DC1 - Device control 1 */,
L"\x2195" /* 18 - DC2 - Device control 2 */, L"\x203C" /* 19 - DC3 - Device control 3 */,
L"\xB6" /* 20 - DC4 - Device control 4 */, L"\xA7" /* 21 - NAK - Negative ACK */,
L"\x25AC" /* 22 - SYN - Synchronous idle */, L"\x21A8" /* 23 - ETB - End of transm. block */,
L"\x2191" /* 24 - CAN - Cancel */, L"\x2193" /* 25 - EM - End of medium */,
L"\x2192" /* 26 - SUB - Substitute */, L"\x2190" /* 27 - ESC - Escape */,
L"\x221F" /* 28 - FS - File separator */, L"\x2194" /* 29 - GS - Group separator */,
L"\x25B2" /* 30 - RS - Record separator */, L"\x25BC" /* 31 - US - Unit separator */,
L"\x20" /* 32 - Space */};
$ for (int y = 0; y < 16; y++, addr += 16)
{
if (cp != 1251) SetConsoleOutputCP (cp = 1251); //-V581
(void)_setmode (stdout_fileno, mode = oldMode);
txSetConsoleAttr (FOREGROUND_YELLOW);
printf ("\n" "%*p ", (int) sizeof (address) * 2, addr);
int color = FOREGROUND_LIGHTGREEN;
for (unsigned x = 0; x < 16; x++)
{
txSetConsoleAttr (color + x/4%2); //-V112
printf ("%02X ", addr[x]);
}
for (unsigned x = 0; x < 16; x++)
{
txSetConsoleAttr (color + x/4%2); //-V112
unsigned char ch = addr[x];
if (ch >= sizearr (xlat) || !istty)
{
if (cp != oldCP) SetConsoleOutputCP (cp = oldCP); //-V581
if (mode != oldMode) (void)_setmode (stdout_fileno, mode = oldMode);
printf ("%c", !strchr ("\t\r\n", ch)? ch : ' ');
}
else
{
if (cp != 1251) SetConsoleOutputCP (cp = 1251); //-V581
if (mode != _o_u16text) (void)_setmode (stdout_fileno, mode = _o_u16text);
wprintf (L"%lls", xlat[ch]);
}
}
}
$ (void)_setmode (stdout_fileno, oldMode);
$ printf ("\n");
$ if (pause && istty)
{
$ txSetConsoleAttr (FOREGROUND_DARKGRAY);
$ txPause ("\v%-*s CodePage = %5u", (int) sizeof (void*) * 2 + 16*3, "[Нажмите любую клавишу для продолжения]", oldCP);
}
$ txSetConsoleAttr (FOREGROUND_LIGHTGRAY);
$ printf ("\n");
$ txSetConsoleAttr (attr);
$ SetConsoleOutputCP (oldCP);
}
//-----------------------------------------------------------------------------------------------------------------
void _txStackBackTrace (const char file[] /*= "?"*/, int line /*= 0*/, const char func[] /*= "?"*/,
bool readSource /*= true*/)
{
$1 unsigned attr = txGetConsoleAttr();
$ txSetConsoleAttr (FOREGROUND_LIGHTCYAN);
$ fprintf (stderr, "\n" "--------------------------------------------------\n"
"Трассировка стека из \"%s\" at %s:%d:\n\n"
"%s\n\n"
"--------------------------------------------------\n\n",
func, file, line, _txCaptureStackBackTrace (1, readSource));
$ txSetConsoleAttr (attr);
}
//-----------------------------------------------------------------------------------------------------------------
char* txDemangle (const char* mangledName, std::nomeow_t)
{
$1 if (!mangledName) return NULL;
$ char* typeName = NULL;
#if defined (_GCC_VER)
$ int err = 1;
$ typeName = ::abi::__cxa_demangle (mangledName, 0, 0, &err); (void) err;
if (typeName) {$ return typeName; }
#endif
$ unsigned short flags = 0;
$ if (mangledName[0] == '.')
{
$ mangledName++;
$ flags = 0x2800; // UNDNAME_32_BIT_DECODE | UNDNAME_TYPE_ONLY
}
$ typeName = _TX_CALL (Win32::__unDName, (NULL, mangledName, 0, malloc, free, flags));
if (typeName) {$ return typeName; }
$ return _strdup (mangledName);
}
//-----------------------------------------------------------------------------------------------------------------
std::string txDemangle (const char* mangledName)
{
$1 char* typeName = txDemangle (mangledName, std::nomeow);
$ std::string name (typeName? typeName : "");
$ free (typeName);
$ return name;
}
//-----------------------------------------------------------------------------------------------------------------
double txQueryPerformance()
{
$1 int maxTime = 500;
$ int maxSamples = 100;
$ POINT size = {100, 100};
$ HDC dc = _txBuffer_Create (txWindow(), &size, NULL);
$ assert (dc); if (!dc) return -1; //-V547
$ DWORD mask = (DWORD) SetThreadAffinityMask (GetCurrentThread(), 1); //-V202
$ assert (mask);
$ LARGE_INTEGER freq = {};
$ QueryPerformanceFrequency (&freq) asserted;
$ LARGE_INTEGER start = {};
$ QueryPerformanceCounter (&start) asserted;
$ int samples = 0;
$ while (samples++ < maxSamples)
{
$ LARGE_INTEGER cur = {};
$ QueryPerformanceCounter (&cur) asserted;
$ double t = 1000.0 * (double) (cur.QuadPart - start.QuadPart) / (double) freq.QuadPart;
$ if (t > maxTime) break;
// Draw test scene
$ for (int y = 0; y < size.y; y++)
for (int x = 0; x < size.x; x++) txSetPixel (x, y, TX_BLACK, dc);
$ for (int y = 0; y < size.y; y += 10)
for (int x = 0; x < size.x; x += 50) txTextOut (x, y, "*", dc);
$ txEllipse (0, 0, size.x, size.y, dc);
$ txFloodFill (size.x/2.0, size.y/2.0, TX_TRANSPARENT, FLOODFILLSURFACE, dc);
$ txBitBlt (dc, size.x/2.0, 0, size.x/2.0, size.y/2.0, dc, 0, 0) asserted;
$ txBitBlt (dc, size.x/2.0, size.y/2.0, size.x/2.0, size.y/2.0, dc, 0, size.y/2.0) asserted;
$ txBitBlt (dc, 0, size.y/2.0, size.x/2.0, size.y/2.0, dc, 0, 0) asserted;
$ txBitBlt (dc, size.x/2.0, size.y/2.0, size.x/2.0, size.y/2.0, dc, size.x/2.0, 0) asserted;
}
$ mask = (DWORD) SetThreadAffinityMask (GetCurrentThread(), mask); //-V106 //-V202
$ assert (mask);
$ _txBuffer_Delete (&dc);
$ return 3.0 * samples / sqrt (1.0 * size.x * size.y);
}
//-----------------------------------------------------------------------------------------------------------------
unsigned txExtractColor (COLORREF color, COLORREF component)
{
$1 switch (component)
{
case TX_RED:
case TX_HUE: $ return (color >> 0) & 0xFF;
case TX_GREEN:
case TX_SATURATION: $ return (color >> 8) & 0xFF;
case TX_BLUE:
case TX_LIGHTNESS: $ return (color >> 16) & 0xFF;
default: $ return CLR_INVALID;
}
}
//-----------------------------------------------------------------------------------------------------------------
COLORREF txRGB2HSL (COLORREF rgbColor)
{
$1 struct xRGB
{
static bool zero (double val)
{
const double prec = 0.001;
return (fabs (val) < prec);
}
};
$ double r = txExtractColor (rgbColor, TX_RED) / 255.0, //-V2551
g = txExtractColor (rgbColor, TX_GREEN) / 255.0, //-V2551
b = txExtractColor (rgbColor, TX_BLUE) / 255.0, //-V2551
m1 = MAX (MAX (r, g), b),
m2 = MIN (MIN (r, g), b),
dm = m1 - m2,
sm = m1 + m2,
h = 0,
s = 0,
l = sm / 2;
$ if (!xRGB::zero (dm))
{
$ sm = (sm <= 1)? sm : (2-sm);
$ s = (!xRGB::zero (sm))? dm/sm : 0;
$ double cr = (!xRGB::zero (dm))? (m1 - r) / dm : 0,
cg = (!xRGB::zero (dm))? (m1 - g) / dm : 0,
cb = (!xRGB::zero (dm))? (m1 - b) / dm : 0;
$ if (xRGB::zero (r - m1)) h = cb - cg;
$ if (xRGB::zero (g - m1)) h = 2 + cr - cb;
$ if (xRGB::zero (b - m1)) h = 4 + cg - cr;
}
$ h = (h >= 0)? h*60 : h*60 + 360;
$ return RGB (ROUND (h / 360.0 * 256), ROUND (s * 255), ROUND (l * 255));
}
//-----------------------------------------------------------------------------------------------------------------
COLORREF txHSL2RGB (COLORREF hslColor)
{
$1 struct xRGB
{
static double calc (double h, double m1, double m2)
{
$2 while (h < 0) h += 360;
$ while (h > 360) h -= 360;
$ return (h < 60)? m1 + (m2-m1) * h / 60 :
(h < 180)? m2 :
(h < 240)? m1 + (m2-m1) * (240-h) / 60 :
m1;
}
};
$ int si = txExtractColor (hslColor, TX_SATURATION);
$ double h = txExtractColor (hslColor, TX_HUE) / 256.0 * 360,
s = txExtractColor (hslColor, TX_SATURATION) / 255.0,
l = txExtractColor (hslColor, TX_LIGHTNESS) / 255.0,
m2 = (l <= 0.5)? l * (1 + s) : l + s - l * s,
m1 = 2 * l - m2,
r = (si)? xRGB::calc (h + 120, m1, m2) : l,
g = (si)? xRGB::calc (h, m1, m2) : l,
b = (si)? xRGB::calc (h - 120, m1, m2) : l;
$ return RGB (ROUND (r * 255), ROUND (g * 255), ROUND (b * 255));
}
//-----------------------------------------------------------------------------------------------------------------
void tx_fpreset()
{
$1 txAutoLock _lock;
$ Win32::_fpreset();
$ unsigned new87 = 0x0008001C; // _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW
#if !defined (__CYGWIN__)
$ unsigned old87 = 0;
$ if (_controlfp_s (&old87, 0, 0) == 0)
{$ (void) _controlfp_s (&old87, old87 & ~new87, 0x0008001F); } // _MCW_EM
#else
$ Win32::_controlfp (Win32::_controlfp (0, 0) & ~new87, 0x0008001F); // _MCW_EM
#endif
}
#endif // TX_COMPILED
//-----------------------------------------------------------------------------------------------------------------
#if defined (_TX_CPP11)
template <int txFramesToAverage>
#endif
double txGetFPS (int minFrames)
{
$1 static _tx_thread LARGE_INTEGER time0 = {}; if (!time0.QuadPart) QueryPerformanceCounter (&time0);
$ LARGE_INTEGER time = {}; QueryPerformanceCounter (&time);
$ if (time.QuadPart - time0.QuadPart == 0)
{$ return 0; }
$ LARGE_INTEGER freq = {}; QueryPerformanceFrequency (&freq);
$ double fps = (double) freq.QuadPart / (double) (time.QuadPart - time0.QuadPart);
$ time0 = time;
$ if (txFramesToAverage == 0) return fps;
$ static _tx_thread double average [txFramesToAverage] = {};
$ static _tx_thread unsigned n = 0;
$ average [n++ % txFramesToAverage] = fps;
$ unsigned nn = MIN (n, (unsigned) sizearr (average));
$ fps = 0;
$ for (unsigned i = 0; i < nn; i++) fps += average[i];
$ fps /= nn;
$ return ((int)n >= MIN (minFrames, txFramesToAverage))? fps : 0;
}
//-----------------------------------------------------------------------------------------------------------------
template <typename T>
inline T zero() { T __zero = {}; return __zero; }
//-----------------------------------------------------------------------------------------------------------------
inline double random (std::nomeow_t, double left, double right)
{
return left + (right - left) * ((double) rand() / RAND_MAX);
}
//-----------------------------------------------------------------------------------------------------------------
template <typename Tx, typename Ta, typename Tb>
inline bool In (std::nomeow_t, Tx x, Ta a, Tb b)
{
return a <= x && x <= b;
}
//-----------------------------------------------------------------------------------------------------------------
inline bool In (std::nomeow_t, const POINT& pt, const RECT& rect)
{
if (_TX_ARGUMENT_FAILED (&pt)) return false;
if (_TX_ARGUMENT_FAILED (&rect)) return false;
return In (std::nomeow, pt.x, rect.left, rect.right) &&
In (std::nomeow, pt.y, rect.top, rect.bottom);
}
//-----------------------------------------------------------------------------------------------------------------
inline bool In (std::nomeow_t, const COORD& pt, const SMALL_RECT& rect)
{
if (_TX_ARGUMENT_FAILED (&pt)) return false;
if (_TX_ARGUMENT_FAILED (&rect)) return false;
return In (std::nomeow, pt.X, rect.Left, rect.Right) &&
In (std::nomeow, pt.Y, rect.Top, rect.Bottom);
}
//-----------------------------------------------------------------------------------------------------------------
inline int random (int range)
{
if (rand() % 100 == 0) fprintf (stderr, "%.4s ", (const volatile char*) ((rand() & 0x0F)? &_txCanaryFirst : &_txCanaryLast)); //-V206
return rand() % range;
}
//-----------------------------------------------------------------------------------------------------------------
inline double random (double left, double right)
{
if (rand() % 100 == 0) fprintf (stderr, "%.4s ", (const volatile char*) ((rand() & 0x0F)? &_txCanaryFirst : &_txCanaryLast)); //-V206
return random (std::nomeow, left, right);
}
//-----------------------------------------------------------------------------------------------------------------
template <typename Tx, typename Ta, typename Tb>
inline bool In (Tx x, Ta a, Tb b)
{
if (rand() % 100 == 0) fprintf (stderr, "%.4s ", (const volatile char*) ((rand() & 0x0F)? &_txCanaryFirst : &_txCanaryLast)); //-V206
return In (std::nomeow, x, a, b);
}
//-----------------------------------------------------------------------------------------------------------------
inline bool In (const POINT& pt, const RECT& rect)
{
if (rand() % 100 == 0) fprintf (stderr, "%.4s ", (const volatile char*) ((rand() & 0x0F)? &_txCanaryFirst : &_txCanaryLast)); //-V206
return In (std::nomeow, pt, rect);
}
//-----------------------------------------------------------------------------------------------------------------
inline bool In (const COORD& pt, const SMALL_RECT& rect)
{
if (rand() % 100 == 0) fprintf (stderr, "%.4s ", (const volatile char*) ((rand() & 0x0F)? &_txCanaryFirst : &_txCanaryLast)); //-V206
return In (std::nomeow, pt, rect);
}
//}
//=================================================================================================================
//=================================================================================================================
//{ txPrintf() implementation
// Реализация txPrintf()
//=================================================================================================================
#if defined (_TX_CPP11)
template <typename T, typename... ArgsT> void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, const T& arg, ArgsT... args);
template <typename T, typename... ArgsT> void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, width_t width, const T& arg, ArgsT... args);
template <typename T, typename... ArgsT> void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, precision_t prec, const T& arg, ArgsT... args);
template <typename T, typename... ArgsT> void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, width_t width, precision_t prec, const T& arg, ArgsT... args);
void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt);
template <typename T> void _txPrintV (std::ostringstream& stream, const char* format, int n, const char*& fmt, const T& arg);
void _txPrintV (std::ostringstream& stream, const char* format, int n, const char*& fmt, int* arg);
void _txPrintV (std::ostringstream& stream, const char* format, int n, const char*& fmt);
//-----------------------------------------------------------------------------------------------------------------
template <typename T, typename... ArgsT>
void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, const T& arg, ArgsT... args)
{
$1 assert (fmt);
$ _txPrintV (stream, format, n, fmt);
if (fmt[0] == '%') {$}
else {$ TX_ERROR ("\"%%$\" required to print an argument in ...\"%s\" while printing %s argument %d in \"%s\"", fmt, txTypename (arg), n, format); }
$ _txPrintV (stream, format, n, fmt, arg);
$ _txPrintF (stream, format, n+1, fmt, args...);
}
//-----------------------------------------------------------------------------------------------------------------
template <typename T, typename... ArgsT>
void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, width_t width, const T& arg, ArgsT... args)
{
$1 assert (&stream);
$ assert (fmt);
$ _txPrintV (stream, format, n, fmt);
if (fmt[0] == '%' && fmt[1] == '*') {$ stream << std::setw (width); } //-V2006
else {$ TX_ERROR ("\"%%*\" required to setwidth (%d) in ...\"%s\" while printing %s argument %d in \"%s\"", width, fmt, txTypename (arg), n, format); }
$ _txPrintV (stream, format, n, fmt, arg);
$ _txPrintF (stream, format, n+1, fmt, args...);
}
//-----------------------------------------------------------------------------------------------------------------
template <typename T, typename... ArgsT>
void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, precision_t prec, const T& arg, ArgsT... args)
{
$1 assert (&stream);
$ assert (fmt);
$ _txPrintV (stream, format, n, fmt);
if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '*') {$ stream << std::setprecision ((std::streamsize) (prec + 1)); } //-V2006 //-V1028
else {$ TX_ERROR ("\"%%.*\" required to setprecision (%d) in ...\"%s\" while printing %s argument %d in \"%s\"", prec, fmt, txTypename (arg), n, format); }
$ _txPrintV (stream, format, n, fmt, arg);
$ _txPrintF (stream, format, n+1, fmt, args...);
}
//-----------------------------------------------------------------------------------------------------------------
template <typename T, typename... ArgsT>
void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt, width_t width, precision_t prec, const T& arg, ArgsT... args)
{
$1 assert (&stream);
$ assert (fmt);
$ _txPrintV (stream, format, n, fmt);
if (fmt[0] == '%' && fmt[1] == '*' && fmt[2] == '.' && fmt[3] == '*') {$ stream << std::setw (width) << std::setprecision ((std::streamsize) (prec + 1)); } //-V2006 //-V1028
else {$ TX_ERROR ("\"%%*.*\" required to setwidth (%d) and setprecision (%d) in ...\"%s\" while printing %s argument %d in \"%s\"", width, prec, fmt, txTypename (arg), n, format); }
$ _txPrintV (stream, format, n, fmt, arg);
$ _txPrintF (stream, format, n+1, fmt, args...);
}
//-----------------------------------------------------------------------------------------------------------------
inline void _txPrintF (std::ostringstream& stream, const char* format, int n, const char*& fmt)
{
$1 assert (fmt);
$ _txPrintV (stream, format, n, fmt);
if (!fmt[0]) {$}
else {$ TX_ERROR ("No argument provided for %% in \"%s\" while printing \"%s\"", fmt, format); }
}
//-----------------------------------------------------------------------------------------------------------------
inline void _txPrintV (std::ostringstream& stream, const char*, int, const char*& fmt)
{
$1 assert (&stream);
$ assert (fmt);
$ while (*fmt)
{
if (fmt[0] == '%')
{
if (fmt[1] == '%') fmt++;
else break;
}
stream << *fmt++;
}
$ }
//-----------------------------------------------------------------------------------------------------------------
template <typename T>
void _txPrintV (std::ostringstream& stream, const char* format, int n, const char*& fmt, const T& arg)
{
$1 assert (&stream);
$ assert (fmt);
$ if (_TX_ARGUMENT_FAILED (&arg)) return;
if (fmt[0] == '%') {$}
else {$ TX_ERROR ("\"%%$\" required to print an argument in ...\"%s\" while printing %s argument %d in \"%s\"", fmt, txTypename (arg), n, format); }
$ fmt++;
$ char oldFill = stream.fill (' ');
$ std::ios_base::fmtflags oldFlags = stream.flags();
$ for (;;) switch (*fmt)
{
case '-': $ stream << std::left; fmt++; break;
case '+': $ stream << std::showpos; fmt++; break;
case ' ': $ stream.fill (' '); fmt++; break;
case '#': $ stream << std::showbase; fmt++; break;
case '0': $ stream.fill ('0'); fmt++; break;
default: $ goto end;
}
end:
$ int width = (*fmt != '*')? (int) strtoul (fmt, const_cast <char**> (&fmt), 10) : (fmt++, 0);
$ int prec = (*fmt == '.')? (*++fmt != '*')? (int) strtoul (fmt, const_cast <char**> (&fmt), 10) : (fmt++, 0) : 0;
if (width) {$ stream << std::setw (width); }
if (prec) {$ stream << std::setprecision (prec); }
$ fmt += strspn (fmt, "hljztL");
$ switch (*fmt)
{
case '$':
case '?': $ break;
case 'd':
case 'i':
case 'u': $ stream << std::dec; break;
case 'o': $ stream << std::oct; break;
case 'x': $ stream << std::hex; break;
case 'X': $ stream << std::hex << std::uppercase; break;
case 'f': $ stream << std::fixed; break;
case 'F': $ stream << std::fixed << std::uppercase; break;
case 'e': $ stream << std::scientific; break;
case 'E': $ stream << std::scientific << std::uppercase; break;
case 'g': $ break;
case 'G': $ stream << std::uppercase; break;
case 'a': $ break;
case 'A': $ stream << std::uppercase; break;
case 'c':
case 's':
case 'p': $ break;
default: $ TX_ERROR ("Invalid format '%.1s' at \"%s\" while printing %s argument %d in \"%s\"", fmt, fmt, txTypename (arg), n, format); break;
}
$ fmt++;
if (&arg) {$ stream << arg; }
else {$ stream << "(null)"; }
$ stream.fill (oldFill);
$ stream.flags (oldFlags);
}
//-----------------------------------------------------------------------------------------------------------------
inline void _txPrintV (std::ostringstream& stream, const char* format, int n, const char*& fmt, int* arg) //-V2009
{
$1 assert (fmt);
if (_TX_ARGUMENT_FAILED (arg)) return;
if (fmt[0] == '%' && fmt[1] == 'n') {$}
else {$ TX_ERROR ("\"%%n\" required to store print length in int* argument %d in \"%s\"", n, format); }
$ *arg = (int) stream.str().length(); //-V202
$ fmt += 2;
}
//-----------------------------------------------------------------------------------------------------------------
template <typename T> inline const T& _txPrintfNormalizeArg (const T& arg) { if (_TX_ARGUMENT_FAILED (&arg)) {;} return arg; }
inline const char* _txPrintfNormalizeArg (const std::string& arg) { if (_TX_ARGUMENT_FAILED (&arg)) return NULL; return arg.c_str(); }
//-----------------------------------------------------------------------------------------------------------------
template <typename... ArgsT>
inline int txPrintf (std::ostringstream& stream, const char* format, ArgsT... args)
{
$1 if (_TX_ARGUMENT_FAILED (&stream)) return 0;
$ if (_TX_ARGUMENT_FAILED (&format)) return 0;
$ const char* fmt = format;
$ _txPrintF (stream, format, 2, fmt, _txPrintfNormalizeArg (args)...);
$ return (int) stream.str().length(); //-V202
}
//-----------------------------------------------------------------------------------------------------------------
template <typename... ArgsT>
inline int txPrintf (char buffer[], size_t size, const char* format, ArgsT... args)
{
$1 if (_TX_ARGUMENT_FAILED (&buffer)) return 0;
$ if (_TX_ARGUMENT_FAILED (&format)) return 0;
$ if (size > 0) size--;
$ buffer[size] = 0;
$ if (!size) return 0;
$ std::ostringstream stream;
$ stream.rdbuf() -> pubsetbuf (buffer, size);
$ txPrintf (stream, format, args...);
$ return (int) stream.str().length(); //-V202
}
//-----------------------------------------------------------------------------------------------------------------
template <typename... ArgsT>
inline std::string txFormat (const char* format, ArgsT... args)
{
$1 if (_TX_ARGUMENT_FAILED (&format)) return "";
$ std::ostringstream stream;
$ txPrintf (stream, format, args...);
$ return stream.str();
}
//-----------------------------------------------------------------------------------------------------------------
template <typename... ArgsT>
inline int txPrintf (const char* format, ArgsT... args)
{
$1 if (_TX_ARGUMENT_FAILED (&format)) return 0;
$ return printf ("%s", txFormat (format, args...) .c_str());
}
#endif
//-----------------------------------------------------------------------------------------------------------------
int _txPrintfCheck (const char* format, ...) tx_printfy (1);
inline int _txPrintfCheck (const char*, ...) { return 0; }
//}
//=================================================================================================================
//=================================================================================================================
//{ txDialog methods implementation
// Реализация методов класса txDialog
//
// See [1] http://msdn.microsoft.com/ru-ru/library/windows/desktop/ms645389%28v=vs.85%29.aspx
// [2] http://blogs.msdn.microsoft.com/oldnewthing/20050429-00/?p=35743
// [3] http://blogs.msdn.microsoft.com/oldnewthing/20040623-00/?p=38753
//=================================================================================================================
#ifndef TX_COMPILED // <<< THE CODE IS HERE, UNFOLD IT <<<
txDialog::txDialog () :
layout_ (NULL)
{$1}
//-----------------------------------------------------------------------------------------------------------------
txDialog::txDialog (const Layout* layout) :
layout_ (layout)
{$1}
//-----------------------------------------------------------------------------------------------------------------
const txDialog::Layout* txDialog::setLayout (const Layout* layout)
{
$1 assert (layout);
$ return ::std::swap (layout_, layout), layout;
}
//-----------------------------------------------------------------------------------------------------------------
intptr_t txDialog::dialogBox (WORD resourceID)
{
$1 const char* resName = (char*)(uintptr_t) resourceID;
$ if (!FindResource (NULL, resName, RT_DIALOG)) return TX_DEBUG_ERROR ("Не найден ресурс диалога %d", resourceID), 0;
$ return DialogBoxParam (NULL, resName, NULL, (DLGPROC) DialogProc_, (LPARAM) this);
}
//-----------------------------------------------------------------------------------------------------------------
intptr_t txDialog::dialogBox (const txDialog::Layout* layout /*= NULL*/, size_t bufsize /*= 0*/)
{
$1 if (!layout) layout = layout_;
$ if (!layout) return TX_DEBUG_ERROR ("Не установлен динамический шаблон диалога"), 0;
$ if (!bufsize) bufsize = 1024;
$ DLGTEMPLATE* tmpl = (DLGTEMPLATE*) GlobalAlloc (GPTR, bufsize);
$ if (!tmpl) return TX_DEBUG_ERROR ("GlobalAlloc(): Нет памяти для шаблона диалога"), 0;
$ const Layout* dlg = &layout[0];
$ const Layout def = { DIALOG, NULL, 0, 0,0,0,0, WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_CENTER, "MS Shell Dlg", 8 };
$ void* ptr = _tx_DLGTEMPLATE_Create (tmpl, bufsize,
(dlg->style? dlg->style : def.style) | DS_SETFONT, 0, 0,
dlg->x, dlg->y, dlg->sx, dlg->sy,
dlg->caption? dlg->caption : def.caption,
dlg->font? dlg->font : def.font,
dlg->fontsize? dlg->fontsize : def.fontsize, NULL);
$ WORD i = 0;
$ for (i = 1; layout[i].wndclass != END; ++i)
{
$ const Layout* item = &layout[i];
$ ptr = _tx_DLGTEMPLATE_Add (ptr, bufsize - ((char*)ptr - (char*)tmpl),
item->style | WS_VISIBLE, 0, item->x, item->y, item->sx, item->sy,
item->id, (const char*)(uintptr_t) item->wndclass, item->caption);
}
$ tmpl->cdit = (unsigned short) (i-1);
$ intptr_t res = DialogBoxIndirectParam (NULL, tmpl, NULL, (DLGPROC) DialogProc_, (LPARAM) this);
$ GlobalFree (tmpl);
$ return res;
}
//-----------------------------------------------------------------------------------------------------------------
int txDialog::dialogProc (HWND wnd, UINT msg, WPARAM wParam, LPARAM)
{
$1 switch (msg)
{
case WM_INITDIALOG: $ SetForegroundWindow (wnd);
$ break;
case WM_COMMAND: $ switch (LOWORD (wParam))
{
case IDOK:
case IDCANCEL: $ SetForegroundWindow (txWindow()? txWindow() : Win32::GetConsoleWindow());
$ EndDialog (wnd, (uintptr_t) this);
$ break;
default: $ break;
}
$ break;
default: $ break;
}
$ return FALSE;
}
//-----------------------------------------------------------------------------------------------------------------
intptr_t CALLBACK txDialog::DialogProc_ (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
$1 static txDialog* this__ = NULL;
$ if (msg == WM_INITDIALOG) this__ = (txDialog*) lParam;
$ if (!this__) return FALSE;
$ return this__-> dialogProc (wnd, msg, wParam, lParam); //-V109
}
//-----------------------------------------------------------------------------------------------------------------
void* _tx_DLGTEMPLATE_Create (void* globalMem, size_t bufsize, DWORD style, DWORD exStyle,
WORD controls, short x, short y, short cx, short cy,
const char caption[], const char font[], WORD fontsize, const char menu[])
{
$1 if (_TX_ARGUMENT_FAILED (globalMem)) return NULL;
$ WORD* pw = (WORD*) globalMem;
$ DLGTEMPLATE* tmpl = ((DLGTEMPLATE*&) pw)++;
$ tmpl->style = style;
$ tmpl->dwExtendedStyle = exStyle;
$ tmpl->cdit = controls;
$ tmpl->x = x;
$ tmpl->y = y;
$ tmpl->cx = cx;
$ tmpl->cy = cy;
$ if (menu > (const char*) 0xFFFF)
{
$ pw += MultiByteToWideChar (_TX_CODEPAGE, 0, (menu? menu : ""), -1, (wchar_t*) pw, //-V547
(int) (bufsize? bufsize - ((char*) pw - (char*) globalMem) : 0xFFFF)); //-V202
}
else
{
$ *pw++ = (WORD)(uintptr_t) (menu? 0xFFFF : 0);
$ *pw++ = (WORD)(uintptr_t) menu;
}
$ if (caption)
{
$ pw += MultiByteToWideChar (_TX_CODEPAGE, 0, (caption? caption : ""), -1, (wchar_t*) pw, //-V547
(int) (bufsize? bufsize - ((char*) pw - (char*) globalMem) : 0xFFFF)); //-V202
}
$ if (style & DS_SETFONT)
{
$ *pw++ = fontsize;
$ pw += MultiByteToWideChar (_TX_CODEPAGE, 0, (font? font : ""), -1, (wchar_t*) pw,
(int) (bufsize? bufsize - ((char*) pw - (char*) globalMem) : 0xFFFF)); //-V202
}
$ return pw;
}
//-----------------------------------------------------------------------------------------------------------------
void* _tx_DLGTEMPLATE_Add (void* dlgTemplatePtr, size_t bufsize, DWORD style, DWORD exStyle,
short x, short y, short cx, short cy,
WORD id, const char wclass[], const char caption[])
{
$1 if (_TX_ARGUMENT_FAILED (dlgTemplatePtr)) return NULL;
$ WORD* pw = (LPWORD) dlgTemplatePtr; // Force align at word boundary
$ ((ULONG&) pw) += 3; //-V205
$ ((ULONG&) pw) >>= 2; //-V205
$ ((ULONG&) pw) <<= 2; //-V205
$ DLGITEMTEMPLATE* tmpl = ((DLGITEMTEMPLATE*&) pw)++;
$ tmpl->style = style;
$ tmpl->dwExtendedStyle = exStyle;
$ tmpl->x = x;
$ tmpl->y = y;
$ tmpl->cx = cx;
$ tmpl->cy = cy;
$ tmpl->id = id;
$ if (HIWORD (wclass) == 0xFFFF)
{
$ *pw++ = (WORD) (HIWORD ((uintptr_t) wclass));
$ *pw++ = (WORD) (LOWORD ((uintptr_t) wclass));
}
else if (wclass)
{
$ pw += MultiByteToWideChar (_TX_CODEPAGE, 0, const_cast <char*> (wclass), -1, (wchar_t*) pw,
(int) (bufsize? bufsize - ((char*) pw - (char*) dlgTemplatePtr) : 0xFFFF)); //-V202
}
else
{
$ *pw++ = 0;
}
$ if (caption)
{
$ pw += MultiByteToWideChar (_TX_CODEPAGE, 0, caption, -1, (wchar_t*) pw,
(int) (bufsize? bufsize - ((char*) pw - (char*) dlgTemplatePtr) : 0xFFFF)); //-V202
}
else
{
$ *pw++ = 0;
}
$ *pw++ = 0;
$ return pw;
}
#endif // TX_COMPILED
//}
//=================================================================================================================
//=================================================================================================================
//{ Cleaning up the utility macros
// Очистка служебных макросов
//=================================================================================================================
#undef $
#undef $0
#undef $1
#undef $2
#undef $3
#undef $4
#undef $5
#undef $6
#undef $7
#undef $8
#undef $9
#undef $$
//}
//=================================================================================================================
//! @endcond }
//=================================================================================================================
//{ Experimental Debugging macros
//! @name Экспериментальные отладочные макросы
//=================================================================================================================
//{----------------------------------------------------------------------------------------------------------------
//! @ingroup Misc
//! @brief Отладочная печать переменной во время вычисления выражения или участка кода
//! во время его выполнения.
//!
//! Сделай приятными твои <i>круглые сутки